initialize

This commit is contained in:
Austin 2021-10-29 21:50:08 -04:00
commit 45cc3a1626
301 changed files with 802760 additions and 0 deletions

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
#
html_assets_cdn/
html_renders_cdn/
html_setup/
html_thumbs_cdn/
html_data/Error/uploads/

17
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,17 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "pwa-node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "c:\\Users\\Austin\\Documents\\discordbot.js"
}
]
}

1
AlphalandRawKey.txt Normal file
View File

@ -0,0 +1 @@
MIICWwIBAAKBgQCdVAXab8B6pYnAdVdQCYj9t+KLRQZzgOmEkQDYCY/nj3+O8JMTdL+pZpXtgl0VzQ8PgjjgGz0w8ZxRzkfkE2hfsy7bY/b9nFWEl8OmqP5FrcuWuivpGOdvqI/KN4UsBxp5dxGw3/vCt3T5L9VudUh8n1Kl0cCiqziEkZFGf+7uIQIDAQABAoGAdwMgimUPDbg7xEL/kaQk5Qk9bm0AvE9AVu/523MgUOLUc6S5HXarpdHciJadI+jDA9BWhfEVEPk0bw3EhFvKD6sxvALBl8oHNKfDR7XzrrBhTXaY+3UICleA7tj4dTv667c3sLGvtlge3oicHv1AdHJg+2Us0l5h8T27l/5viSECQQDJzwMDLsydJZzxpS3q20YoWyeseDAhJDpLBEL45+yrdXk/6s+sVM7NY1BkWC0tiTChex2l1TfomuTj+ltVP46rAkEAx5NH2fUftd3T/ZLDTS1Cq7vgqEsSqasA/H19xlJ8L2Z/+ikHPc/5SRjas08dC0WWgDBxdd0q1iyu7FsyFghGYwJAXXwXAidww69D17DT54KyKkmnxD5c1U1p74xG1fTh7r9ZbqGAmG0k64IBIKq0Ku7tZzCYGFUANDFkrLMyEfiCRwJAUhAZh2HnvByOwsHKVL27oGoMoqbb8bBDI49mXFomfkcjcHXWaHBQDOKPaxOo2a2viN5iiRh8OLz+4GlPWwfkCQJALjCq0vhddumD7W/rnXWXsg+Imtqh+CX3yVQ55+Ji6Rmd6bNjMysA1jWHWHYycFFBz5SThCwInBffugHzP+hbLw==

76
IsAliveCheck.php Normal file
View File

@ -0,0 +1,76 @@
<?php
/*
Alphaland 2021
This check seems to show Thumbnail or Gameserver offline every 1 in 2000 checks, probably due to curl or some sort of flood check on the arbiter. TODO: look more into that
*/
//vars
$thumbalive = false;
$gamealive = false;
// ...
//UTIL FUNCTIONS
function checkThumb($override)
{
//thumbnailer check
if (httpGetPing($GLOBALS['thumbnailArbiter'], 5000)) //thumb arbiter online
{
if (!$GLOBALS['thumbalive'] or $override) //to prevent flooding mysql calls
{
$GLOBALS['thumbalive'] = true;
$set = $GLOBALS['pdo']->prepare("UPDATE websettings SET isThumbnailerAlive = 1");
$set->execute();
}
}
else //thumb arbiter offline
{
if ($GLOBALS['thumbalive'] or $override) //to prevent flooding mysql calls
{
$GLOBALS['thumbalive'] = false;
$set = $GLOBALS['pdo']->prepare("UPDATE websettings SET isThumbnailerAlive = 0");
$set->execute();
}
}
// ...
}
function checkGame($override)
{
//gameserver check
if (httpGetPing($GLOBALS['gamesArbiter'], 5000)) //gameserver arbiter online
{
if (!$GLOBALS['gamealive'] or $override) //to prevent flooding mysql calls
{
$GLOBALS['gamealive'] = true;
$set = $GLOBALS['pdo']->prepare("UPDATE websettings SET IsGameServerAlive = 1");
$set->execute();
}
}
else //gameserver arbiter offline
{
if ($GLOBALS['gamealive'] or $override) //to prevent flooding mysql calls
{
$GLOBALS['gamealive'] = false;
$set = $GLOBALS['pdo']->prepare("UPDATE websettings SET IsGameServerAlive = 0");
$set->execute();
}
}
// ...
}
// ...
//first time running, pass true to force a check without SQL query limit restriction
checkGame(true);
checkThumb(true);
// ...
while (true) //EZ
{
//we are in the loop now, run without override
checkGame(false);
checkThumb(false);
// ...
usleep(10000); //if both requests timeout after 5 seconds, the max this script will halt is 20 seconds
}

BIN
PersonalServerOverlay.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

800
RCCService.wsdl Normal file
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,53 @@
<?php
/*
Alphaland 2021
kinda shit but its meant for background render processes so not really a concern
*/
$assetid = $argv[1];
$type = $argv[2];
switch ($type)
{
case "avatar":
RenderPlayer($assetid);
break;
case "avatarcloseup":
RenderPlayerCloseup($assetid);
break;
case "hat":
RenderHat($assetid);
break;
case "tshirt":
RenderTShirt($assetid);
break;
case "shirt":
RenderShirt($assetid);
break;
case "pants":
RenderPants($assetid);
break;
case "face":
RenderFace($assetid);
break;
case "gear":
RenderGear($assetid);
break;
case "head":
RenderHead($assetid);
break;
case "place":
RenderPlace($assetid);
break;
case "package":
RenderPackage($assetid);
break;
case "model":
RenderModel($assetid);
case "mesh":
RenderMesh($assetid);
break;
default:
break;
}

View File

@ -0,0 +1,425 @@
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="Workspace" referent="RBXD3721CB697734B5E88C9AE1946AC0DDD">
<Properties>
<bool name="AllowThirdPartySales">false</bool>
<Ref name="CurrentCamera">RBX7BA3BBD8CCFC4FBF8646AD9D3BEACFFB</Ref>
<double name="DistributedGameTime">0</double>
<bool name="ExpSolverEnabled_Replicate">true</bool>
<float name="FallenPartsDestroyHeight">-500</float>
<bool name="FilteringEnabled">false</bool>
<float name="Gravity">196.199997</float>
<CoordinateFrame name="ModelInPrimary">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<string name="Name">Workspace</string>
<bool name="PGSPhysicsSolverEnabled">true</bool>
<Ref name="PrimaryPart">null</Ref>
<bool name="StreamingEnabled">false</bool>
</Properties>
<Item class="Camera" referent="RBX7BA3BBD8CCFC4FBF8646AD9D3BEACFFB">
<Properties>
<CoordinateFrame name="CFrame">
<X>-169.13916</X>
<Y>21.2607193</Y>
<Z>164.078796</Z>
<R00>0.714415789</R00>
<R01>0.141907141</R01>
<R02>-0.685180724</R02>
<R10>7.4505806e-009</R10>
<R11>0.979219198</R11>
<R12>0.202805176</R12>
<R20>0.699721515</R20>
<R21>-0.144887224</R21>
<R22>0.699569583</R22>
</CoordinateFrame>
<Ref name="CameraSubject">null</Ref>
<token name="CameraType">0</token>
<float name="FieldOfView">70</float>
<CoordinateFrame name="Focus">
<X>-167.768784</X>
<Y>20.8551044</Y>
<Z>162.679642</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<bool name="HeadLocked">true</bool>
<float name="HeadScale">1</float>
<string name="Name">Camera</string>
</Properties>
</Item>
<Item class="Terrain" referent="RBX471E57F39BFC42EBACC00C16CD370F9C">
<Properties>
<bool name="Anchored">true</bool>
<float name="BackParamA">-0.5</float>
<float name="BackParamB">0.5</float>
<token name="BackSurface">0</token>
<token name="BackSurfaceInput">0</token>
<float name="BottomParamA">-0.5</float>
<float name="BottomParamB">0.5</float>
<token name="BottomSurface">4</token>
<token name="BottomSurfaceInput">0</token>
<int name="BrickColor">194</int>
<CoordinateFrame name="CFrame">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<bool name="CanCollide">true</bool>
<BinaryString name="ClusterGridV3"></BinaryString>
<Color3uint8 name="Color3uint8">4288914085</Color3uint8>
<PhysicalProperties name="CustomPhysicalProperties">
<CustomPhysics>false</CustomPhysics>
</PhysicalProperties>
<float name="Elasticity">0.300000012</float>
<float name="Friction">0.5</float>
<float name="FrontParamA">-0.5</float>
<float name="FrontParamB">0.5</float>
<token name="FrontSurface">0</token>
<token name="FrontSurfaceInput">0</token>
<float name="LeftParamA">-0.5</float>
<float name="LeftParamB">0.5</float>
<token name="LeftSurface">0</token>
<token name="LeftSurfaceInput">0</token>
<bool name="Locked">true</bool>
<token name="Material">256</token>
<string name="Name">Terrain</string>
<float name="Reflectance">0</float>
<float name="RightParamA">-0.5</float>
<float name="RightParamB">0.5</float>
<token name="RightSurface">0</token>
<token name="RightSurfaceInput">0</token>
<Vector3 name="RotVelocity">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
</Vector3>
<BinaryString name="SmoothGrid"></BinaryString>
<float name="TopParamA">-0.5</float>
<float name="TopParamB">0.5</float>
<token name="TopSurface">3</token>
<token name="TopSurfaceInput">0</token>
<float name="Transparency">0</float>
<Vector3 name="Velocity">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
</Vector3>
<Color3 name="WaterColor">4278998108</Color3>
<float name="WaterTransparency">0.300000012</float>
<float name="WaterWaveSize">0.150000006</float>
<float name="WaterWaveSpeed">10</float>
<Vector3 name="size">
<X>2044</X>
<Y>252</Y>
<Z>2044</Z>
</Vector3>
</Properties>
</Item>
<Item class="Part" referent="RBX9F47F782C640466FB095B8788CB980D7">
<Properties>
<bool name="Anchored">true</bool>
<float name="BackParamA">-0.5</float>
<float name="BackParamB">0.5</float>
<token name="BackSurface">0</token>
<token name="BackSurfaceInput">0</token>
<float name="BottomParamA">-0.5</float>
<float name="BottomParamB">0.5</float>
<token name="BottomSurface">4</token>
<token name="BottomSurfaceInput">0</token>
<int name="BrickColor">199</int>
<CoordinateFrame name="CFrame">
<X>0</X>
<Y>-10</Y>
<Z>0</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<bool name="CanCollide">true</bool>
<Color3uint8 name="Color3uint8">4284702562</Color3uint8>
<PhysicalProperties name="CustomPhysicalProperties">
<CustomPhysics>false</CustomPhysics>
</PhysicalProperties>
<float name="Elasticity">0.5</float>
<float name="Friction">0.300000012</float>
<float name="FrontParamA">-0.5</float>
<float name="FrontParamB">0.5</float>
<token name="FrontSurface">0</token>
<token name="FrontSurfaceInput">0</token>
<float name="LeftParamA">-0.5</float>
<float name="LeftParamB">0.5</float>
<token name="LeftSurface">0</token>
<token name="LeftSurfaceInput">0</token>
<bool name="Locked">true</bool>
<token name="Material">256</token>
<string name="Name">BasePlate</string>
<float name="Reflectance">0</float>
<float name="RightParamA">-0.5</float>
<float name="RightParamB">0.5</float>
<token name="RightSurface">0</token>
<token name="RightSurfaceInput">0</token>
<Vector3 name="RotVelocity">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
</Vector3>
<float name="TopParamA">-0.5</float>
<float name="TopParamB">0.5</float>
<token name="TopSurface">3</token>
<token name="TopSurfaceInput">0</token>
<float name="Transparency">0</float>
<Vector3 name="Velocity">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
</Vector3>
<token name="formFactorRaw">1</token>
<token name="shape">1</token>
<Vector3 name="size">
<X>512</X>
<Y>20</Y>
<Z>512</Z>
</Vector3>
</Properties>
</Item>
</Item>
<Item class="NonReplicatedCSGDictionaryService" referent="RBX5AD369D845894D048FEC1AF2CB5DFC62">
<Properties>
<string name="Name">NonReplicatedCSGDictionaryService</string>
</Properties>
</Item>
<Item class="CSGDictionaryService" referent="RBX4E5A676A5DB24683A112CDA6BB22EEA1">
<Properties>
<string name="Name">CSGDictionaryService</string>
</Properties>
</Item>
<Item class="Players" referent="RBXA2D705D1E0494EEFBD2DFED708B24209">
<Properties>
<bool name="CharacterAutoLoads">true</bool>
<int name="MaxPlayersInternal">12</int>
<string name="Name">Players</string>
<int name="PreferredPlayersInternal">0</int>
</Properties>
</Item>
<Item class="ReplicatedFirst" referent="RBX0E0B79A2A05D42FC81ABF4828AC7AE5B">
<Properties>
<string name="Name">ReplicatedFirst</string>
</Properties>
</Item>
<Item class="StarterPlayer" referent="RBXDABFB40962B74FD9AFEB507717596A1E">
<Properties>
<bool name="AutoJumpEnabled">true</bool>
<float name="CameraMaxZoomDistance">400</float>
<float name="CameraMinZoomDistance">0.5</float>
<token name="CameraMode">0</token>
<token name="DevCameraOcclusionMode">0</token>
<token name="DevComputerCameraMovementMode">0</token>
<token name="DevComputerMovementMode">0</token>
<token name="DevTouchCameraMovementMode">0</token>
<token name="DevTouchMovementMode">0</token>
<bool name="EnableMouseLockOption">true</bool>
<float name="HealthDisplayDistance">100</float>
<bool name="LoadCharacterAppearance">true</bool>
<string name="Name">StarterPlayer</string>
<float name="NameDisplayDistance">100</float>
</Properties>
<Item class="StarterPlayerScripts" referent="RBX951EA0B8A0964461982297D43902A186">
<Properties>
<string name="Name">StarterPlayerScripts</string>
</Properties>
</Item>
<Item class="StarterCharacterScripts" referent="RBX7C82E926764B4F12A26A271D0BAE6D1A">
<Properties>
<string name="Name">StarterCharacterScripts</string>
</Properties>
</Item>
</Item>
<Item class="StarterPack" referent="RBX191BF37018554EC78A06778C4BADB862">
<Properties>
<string name="Name">StarterPack</string>
</Properties>
</Item>
<Item class="StarterGui" referent="RBXBBBB121141A84D4AAA89E2B3B8E48CFA">
<Properties>
<string name="Name">StarterGui</string>
<bool name="ResetPlayerGuiOnSpawn">true</bool>
<bool name="ShowDevelopmentGui">true</bool>
</Properties>
</Item>
<Item class="TeleportService" referent="RBX7EEE491CA5CB41C59E67FEFA9F651841">
<Properties>
<string name="Name">Teleport Service</string>
</Properties>
</Item>
<Item class="SoundService" referent="RBXA43490ED055245C79C1BF3BDCE436E0A">
<Properties>
<token name="AmbientReverb">0</token>
<float name="DistanceFactor">10</float>
<float name="DopplerScale">1</float>
<string name="Name">SoundService</string>
<float name="RolloffScale">1</float>
</Properties>
</Item>
<Item class="CollectionService" referent="RBX0EADFA9D6E584AA89337B2C5DA77487D">
<Properties>
<string name="Name">CollectionService</string>
</Properties>
</Item>
<Item class="PhysicsService" referent="RBX3C6535C805F34DDEB34169CE6BC5AB3A">
<Properties>
<string name="Name">PhysicsService</string>
</Properties>
</Item>
<Item class="Geometry" referent="RBX98278CDACCCF4348A34EEFAB40513DB5">
<Properties>
<string name="Name">Geometry</string>
</Properties>
</Item>
<Item class="RenderHooksService" referent="RBXE8BBEC6ECC5B4E199697441EC61AC180">
<Properties>
<string name="Name">RenderHooksService</string>
</Properties>
</Item>
<Item class="InsertService" referent="RBXFCB8437763C74465BAF10E63C9BF325E">
<Properties>
<bool name="AllowInsertFreeModels">false</bool>
<string name="Name">InsertService</string>
</Properties>
</Item>
<Item class="SocialService" referent="RBXB749344473A84DB48FD2510DEBE289D7">
<Properties>
<string name="Name">SocialService</string>
</Properties>
</Item>
<Item class="GamePassService" referent="RBX1BF2A991F09F42B590CD4BFDECAF9FA1">
<Properties>
<string name="Name">GamePassService</string>
</Properties>
</Item>
<Item class="Debris" referent="RBX9929BCA0AF3A4D0CA2E70F469F20B395">
<Properties>
<int name="MaxItems">1000</int>
<string name="Name">Debris</string>
</Properties>
</Item>
<Item class="TimerService" referent="RBX369ABCD6ED234F13AE19C8F3C5F4BD8C">
<Properties>
<string name="Name">Instance</string>
</Properties>
</Item>
<Item class="ScriptInformationProvider" referent="RBX60B66ACBBDB2414EA75D9B10D59197FA">
<Properties>
<string name="Name">Instance</string>
</Properties>
</Item>
<Item class="CookiesService" referent="RBX9AA683D9E98A404BA0DF69AB165CA341">
<Properties>
<string name="Name">CookiesService</string>
</Properties>
</Item>
<Item class="ContextActionService" referent="RBX41CB20B345674B50B9DC229F3BD0C366">
<Properties>
<string name="Name">ContextActionService</string>
</Properties>
</Item>
<Item class="ScriptService" referent="RBX6A227B787D51497EB95D6A1F483F90F2">
<Properties>
<string name="Name">Instance</string>
</Properties>
</Item>
<Item class="AssetService" referent="RBXC84467C421EB429981E8BC576A34E354">
<Properties>
<string name="Name">AssetService</string>
</Properties>
</Item>
<Item class="Selection" referent="RBX1C7BB0C96D004A88A0A9276EFF281E0E">
<Properties>
<string name="Name">Selection</string>
</Properties>
</Item>
<Item class="ServerScriptService" referent="RBXBF44C7A8B1CB497DB75D843615CA3AC7">
<Properties>
<bool name="LoadStringEnabled">false</bool>
<string name="Name">ServerScriptService</string>
</Properties>
</Item>
<Item class="ServerStorage" referent="RBX089FD06171F242E7AB401AE414B2145E">
<Properties>
<string name="Name">ServerStorage</string>
</Properties>
</Item>
<Item class="ReplicatedStorage" referent="RBX2C6A2259028E43C28B29BE6541F5F7BE">
<Properties>
<string name="Name">ReplicatedStorage</string>
</Properties>
</Item>
<Item class="LuaWebService" referent="RBXF738C1B655274800A3A1A66EB77C2296">
<Properties>
<string name="Name">Instance</string>
</Properties>
</Item>
<Item class="Lighting" referent="RBXF3974B9A3813452E8913045F39D98E1E">
<Properties>
<Color3 name="Ambient">4278190080</Color3>
<float name="Brightness">1</float>
<Color3 name="ColorShift_Bottom">4278190080</Color3>
<Color3 name="ColorShift_Top">4278190080</Color3>
<Color3 name="FogColor">4290822336</Color3>
<float name="FogEnd">100000</float>
<float name="FogStart">0</float>
<float name="GeographicLatitude">41.7332993</float>
<bool name="GlobalShadows">true</bool>
<string name="Name">Lighting</string>
<Color3 name="OutdoorAmbient">4286611584</Color3>
<bool name="Outlines">true</bool>
<Color3 name="ShadowColor">4289967032</Color3>
<string name="TimeOfDay">14:00:00</string>
</Properties>
</Item>
<Item class="HttpService" referent="RBXFB66F43FFB9941E494C2EBF3644EE47F">
<Properties>
<bool name="HttpEnabled">false</bool>
<string name="Name">HttpService</string>
</Properties>
</Item>
<Item class="GamepadService" referent="RBXBE19746EB7694EDC9F8F0E6EB291A43A">
<Properties>
<string name="Name">GamepadService</string>
</Properties>
</Item>
</roblox>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,456 @@
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="Workspace" referent="RBX1411602D53AF4555B144FC2F2F7513D5">
<Properties>
<bool name="AllowThirdPartySales">false</bool>
<Ref name="CurrentCamera">RBX99C6A55784D844429E7450BE32E9D85A</Ref>
<double name="DistributedGameTime">0</double>
<bool name="ExpSolverEnabled_Replicate">true</bool>
<float name="FallenPartsDestroyHeight">-500</float>
<bool name="FilteringEnabled">false</bool>
<float name="Gravity">196.199997</float>
<CoordinateFrame name="ModelInPrimary">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<string name="Name">Workspace</string>
<bool name="PGSPhysicsSolverEnabled">true</bool>
<Ref name="PrimaryPart">null</Ref>
<bool name="StreamingEnabled">false</bool>
</Properties>
<Item class="Camera" referent="RBX99C6A55784D844429E7450BE32E9D85A">
<Properties>
<CoordinateFrame name="CFrame">
<X>-612.292725</X>
<Y>140.803696</Y>
<Z>643.374451</Z>
<R00>0.746464849</R00>
<R01>0.202167332</R01>
<R02>-0.633970499</R02>
<R10>-0</R10>
<R11>0.952730417</R11>
<R12>0.303816944</R12>
<R20>0.665424824</R20>
<R21>-0.22678867</R21>
<R22>0.711179793</R22>
</CoordinateFrame>
<Ref name="CameraSubject">null</Ref>
<token name="CameraType">0</token>
<float name="FieldOfView">70</float>
<CoordinateFrame name="Focus">
<X>-611.02478</X>
<Y>140.19606</Y>
<Z>641.952087</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<bool name="HeadLocked">true</bool>
<float name="HeadScale">1</float>
<string name="Name">Camera</string>
</Properties>
</Item>
<Item class="Terrain" referent="RBX01690DE7F0FC489F963ABFCCE9BE20F9">
<Properties>
<bool name="Anchored">true</bool>
<float name="BackParamA">-0.5</float>
<float name="BackParamB">0.5</float>
<token name="BackSurface">0</token>
<token name="BackSurfaceInput">0</token>
<float name="BottomParamA">-0.5</float>
<float name="BottomParamB">0.5</float>
<token name="BottomSurface">4</token>
<token name="BottomSurfaceInput">0</token>
<int name="BrickColor">194</int>
<CoordinateFrame name="CFrame">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<bool name="CanCollide">true</bool>
<BinaryString name="ClusterGridV3"><![CDATA[+P8AAPn/AP8IACj/OAAB/wgAEf84APj/AAD7/wD/CAAo/zgAAf8IABH/OAABAAAA+f8A/wgA
KP84AAH/CAAR/zgA+P8AAPz/AP8IACj/OAAB/wgAEf84AP7/AAABAAD/CAAo/zgAAf8IABH/
OAD8/wAA+v8A/wgAKP84AAH/CAAR/zgAAQAAAPr/AP8IACj/OAAB/wgAEf84APz/AAD7/wD/
CAAo/zgAAf8IABH/OAACAAAAAAAA/wgAKP84AAH/CAAR/zgA+P8AAP3/AP8IACj/OAAB/wgA
Ef84AP7/AAACAAD/CAAo/zgAAf8IABH/OAD4/wAA/v8A/wgAKP84AAH/CAAR/zgABwAAAPv/
AP8IACj/OAAB/wgAEf84AP3/AAADAAD/CAAo/zgAAf8IABH/OAD4/wAA//8A/wgAKP84AAH/
CAAR/zgABgAAAAcAAP8IACj/OAAB/wgAEf84APr/AAD6/wD/CAAo/zgAAf8IABH/OAABAAAA
+/8A/wgAKP84AAH/CAAR/zgABwAAAPz/AP8IACj/OAAB/wgAEf84AP3/AAAEAAD/CAAo/zgA
Af8IABH/OAAHAAAAAQAA/wgAKP84AAH/CAAR/zgAAQAAAPz/AP8IACj/OAAB/wgAEf84AAcA
AAD9/wD/CAAo/zgAAf8IABH/OAD9/wAABQAA/wgAKP84AAH/CAAR/zgABwAAAAIAAP8IACj/
OAAB/wgAEf84AAEAAAD9/wD/CAAo/zgAAf8IABH/OAAHAAAA/v8A/wgAKP84AAH/CAAR/zgA
/f8AAAYAAP8IACj/OAAB/wgAEf84APj/AAD6/wD/CAAo/zgAAf8IABH/OAAEAAAABwAA/wgA
KP84AAH/CAAR/zgABwAAAAMAAP8IACj/OAAB/wgAEf84AAEAAAD+/wD/CAAo/zgAAf8IABH/
OAD5/wAA+P8A/wgAKP84AAH/CAAR/zgABwAAAAQAAP8IACj/OAAB/wgAEf84AAEAAAD//wD/
CAAo/zgAAf8IABH/OAAHAAAABQAA/wgAKP84AAH/CAAR/zgA+/8AAPj/AP8IACj/OAAB/wgA
Ef84AAcAAAAGAAD/CAAo/zgAAf8IABH/OAD7/wAA+f8A/wgAKP84AAH/CAAR/zgA+P8AAPj/
AP8IACj/OAAB/wgAEf84APr/AAD4/wD/CAAo/zgAAf8IABH/OAD8/wAA+P8A/wgAKP84AAH/
CAAR/zgA//8AAPj/AP8IACj/OAAB/wgAEf84AAAAAAAHAAD/CAAo/zgAAf8IABH/OAAFAAAA
+P8A/wgAKP84AAH/CAAR/zgA/v8AAAcAAP8IACj/OAAB/wgAEf84AAMAAAD4/wD/CAAo/zgA
Af8IABH/OAD9/wAAAQAA/wgAKP84AAH/CAAR/zgABwAAAPn/AP8IACj/OAAB/wgAEf84AP3/
AAD4/wD/CAAo/zgAAf8IABH/OAD4/wAABwAA/wgAKP84AAH/CAAR/zgAAgAAAP//AP8IACj/
OAAB/wgAEf84AAAAAAD4/wD/CAAo/zgAAf8IABH/OAD+/wAA+P8A/wgAKP84AAH/CAAR/zgA
AQAAAPj/AP8IACj/OAAB/wgAEf84AAIAAAAHAAD/CAAo/zgAAf8IABH/OAAHAAAA+P8A/wgA
KP84AAH/CAAR/zgAAgAAAPj/AP8IACj/OAAB/wgAEf84AP3/AAAHAAD/CAAo/zgAAf8IABH/
OAAHAAAA//8A/wgAKP84AAH/CAAR/zgAAwAAAAcAAP8IACj/OAAB/wgAEf84AAQAAAD4/wD/
CAAo/zgAAf8IABH/OAD//wAABwAA/wgAKP84AAH/CAAR/zgABQAAAAcAAP8IACj/OAAB/wgA
Ef84APn/AAD6/wD/CAAo/zgAAf8IABH/OAAGAAAA+P8A/wgAKP84AAH/CAAR/zgAAQAAAAcA
AP8IACj/OAAB/wgAEf84AAcAAAAHAAD/CAAo/zgAAf8IABH/OAD7/wAA+v8A/wgAKP84AAH/
CAAR/zgA+f8AAPn/AP8IACj/OAAB/wgAEf84APr/AAD5/wD/CAAo/zgAAf8IABH/OAD8/wAA
+f8A/wgAKP84AAH/CAAR/zgA/f8AAPn/AP8IACj/OAAB/wgAEf84AP7/AAD5/wD/CAAo/zgA
Af8IABH/OAD//wAA+f8A/wgAKP84AAH/CAAR/zgAAAAAAPn/AP8IACj/OAAB/wgAEf84APj/
AAABAAD/CAAo/zgAAf8IABH/OAACAAAA+f8A/wgAKP84AAH/CAAR/zgA+f8AAPv/AP8IACj/
OAAB/wgAEf84APr/AAD7/wD/CAAo/zgAAf8IABH/OAAAAAAAAAAA/wgAKP84AAH/CAAR/zgA
+/8AAPv/AP8IACj/OAAB/wgAEf84AAEAAAAAAAD/CAAo/zgAAf8IABH/OAD9/wAA+v8A/wgA
KP84AAH/CAAR/zgA/v8AAPr/AP8IACj/OAAB/wgAEf84AP//AAD6/wD/CAAo/zgAAf8IABH/
OAAAAAAA+v8A/wgAKP84AAH/CAAR/zgA+P8AAAIAAP8IACj/OAAB/wgAEf84AAIAAAD6/wD/
CAAo/zgAAf8IABH/OAD9/wAA+/8A/wgAKP84AAH/CAAR/zgAAwAAAAAAAP8IACj/OAAB/wgA
Ef84AP7/AAD7/wD/CAAo/zgAAf8IABH/OAAEAAAAAAAA/wgAKP84AAH/CAAR/zgA//8AAPv/
AP8IACj/OAAB/wgAEf84APj/AAAAAAD/CAAo/zgAAf8IABH/OAAFAAAAAAAA/wgAKP84AAH/
CAAR/zgA+P8AAAMAAP8IACj/OAAB/wgAEf84AAIAAAD7/wD/CAAo/zgAAf8IABH/OAD5/wAA
AwAA/wgAKP84AAH/CAAR/zgAAwAAAPv/AP8IACj/OAAB/wgAEf84APr/AAADAAD/CAAo/zgA
Af8IABH/OAAEAAAA+/8A/wgAKP84AAH/CAAR/zgA+/8AAAMAAP8IACj/OAAB/wgAEf84AAUA
AAD7/wD/CAAo/zgAAf8IABH/OAD8/wAAAwAA/wgAKP84AAH/CAAR/zgABgAAAPv/AP8IACj/
OAAB/wgAEf84APn/AAD8/wD/CAAo/zgAAf8IABH/OAD//wAAAQAA/wgAKP84AAH/CAAR/zgA
+v8AAPz/AP8IACj/OAAB/wgAEf84AAAAAAABAAD/CAAo/zgAAf8IABH/OAD7/wAA/P8A/wgA
KP84AAH/CAAR/zgAAQAAAAEAAP8IACj/OAAB/wgAEf84APz/AAD8/wD/CAAo/zgAAf8IABH/
OAACAAAAAQAA/wgAKP84AAH/CAAR/zgA/f8AAPz/AP8IACj/OAAB/wgAEf84AAMAAAABAAD/
CAAo/zgAAf8IABH/OAD+/wAA/P8A/wgAKP84AAH/CAAR/zgABAAAAAEAAP8IACj/OAAB/wgA
Ef84AP//AAD8/wD/CAAo/zgAAf8IABH/OAAFAAAAAQAA/wgAKP84AAH/CAAR/zgAAAAAAPz/
AP8IACj/OAAB/wgAEf84AAYAAAABAAD/CAAo/zgAAf8IABH/OAD4/wAABAAA/wgAKP84AAH/
CAAR/zgAAgAAAPz/AP8IACj/OAAB/wgAEf84APn/AAAEAAD/CAAo/zgAAf8IABH/OAADAAAA
/P8A/wgAKP84AAH/CAAR/zgA+v8AAAQAAP8IACj/OAAB/wgAEf84AAQAAAD8/wD/CAAo/zgA
Af8IABH/OAD7/wAABAAA/wgAKP84AAH/CAAR/zgABQAAAPz/AP8IACj/OAAB/wgAEf84APz/
AAAEAAD/CAAo/zgAAf8IABH/OAAGAAAA/P8A/wgAKP84AAH/CAAR/zgA+f8AAP3/AP8IACj/
OAAB/wgAEf84AP//AAACAAD/CAAo/zgAAf8IABH/OAD4/wAABQAA/wgAKP84AAH/CAAR/zgA
AgAAAP3/AP8IACj/OAAB/wgAEf84APn/AAAFAAD/CAAo/zgAAf8IABH/OAADAAAA/f8A/wgA
KP84AAH/CAAR/zgA+v8AAAUAAP8IACj/OAAB/wgAEf84AAQAAAD9/wD/CAAo/zgAAf8IABH/
OAD7/wAABQAA/wgAKP84AAH/CAAR/zgABQAAAP3/AP8IACj/OAAB/wgAEf84APz/AAAFAAD/
CAAo/zgAAf8IABH/OAAGAAAA/f8A/wgAKP84AAH/CAAR/zgAAAAAAAQAAP8IACj/OAAB/wgA
Ef84APr/AAD//wD/CAAo/zgAAf8IABH/OAABAAAABAAA/wgAKP84AAH/CAAR/zgA+/8AAP//
AP8IACj/OAAB/wgAEf84APn/AAAHAAD/CAAo/zgAAf8IABH/OAADAAAA//8A/wgAKP84AAH/
CAAR/zgAAwAAAPn/AP8IACj/OAAB/wgAEf84APn/AAABAAD/CAAo/zgAAf8IABH/OAD6/wAA
BwAA/wgAKP84AAH/CAAR/zgABAAAAP//AP8IACj/OAAB/wgAEf84AAQAAAD5/wD/CAAo/zgA
Af8IABH/OAD6/wAAAQAA/wgAKP84AAH/CAAR/zgA+/8AAAcAAP8IACj/OAAB/wgAEf84AAUA
AAD//wD/CAAo/zgAAf8IABH/OAAFAAAA+f8A/wgAKP84AAH/CAAR/zgA+/8AAAEAAP8IACj/
OAAB/wgAEf84AAYAAAD5/wD/CAAo/zgAAf8IABH/OAD8/wAAAQAA/wgAKP84AAH/CAAR/zgA
/P8AAAcAAP8IACj/OAAB/wgAEf84AAYAAAD//wD/CAAo/zgAAf8IABH/OAD7/wAABgAA/wgA
KP84AAH/CAAR/zgABQAAAP7/AP8IACj/OAAB/wgAEf84AAYAAAD+/wD/CAAo/zgAAf8IABH/
OAD8/wAABgAA/wgAKP84AAH/CAAR/zgAAAAAAAUAAP8IACj/OAAB/wgAEf84AAcAAAAAAAD/
CAAo/zgAAf8IABH/OAD6/wAAAAAA/wgAKP84AAH/CAAR/zgAAQAAAAUAAP8IACj/OAAB/wgA
Ef84APv/AAAAAAD/CAAo/zgAAf8IABH/OAADAAAA+v8A/wgAKP84AAH/CAAR/zgA+f8AAAIA
AP8IACj/OAAB/wgAEf84AAQAAAD6/wD/CAAo/zgAAf8IABH/OAD6/wAAAgAA/wgAKP84AAH/
CAAR/zgAAAAAAPv/AP8IACj/OAAB/wgAEf84APn/AAAAAAD/CAAo/zgAAf8IABH/OAAGAAAA
AAAA/wgAKP84AAH/CAAR/zgABQAAAPr/AP8IACj/OAAB/wgAEf84APv/AAACAAD/CAAo/zgA
Af8IABH/OAD//wAA/f8A/wgAKP84AAH/CAAR/zgABQAAAAIAAP8IACj/OAAB/wgAEf84AAAA
AAD9/wD/CAAo/zgAAf8IABH/OAAGAAAAAgAA/wgAKP84AAH/CAAR/zgA//8AAP7/AP8IACj/
OAAB/wgAEf84AAUAAAADAAD/CAAo/zgAAf8IABH/OAD//wAABAAA/wgAKP84AAH/CAAR/zgA
+f8AAP//AP8IACj/OAAB/wgAEf84AAAAAAD+/wD/CAAo/zgAAf8IABH/OAAGAAAAAwAA/wgA
KP84AAH/CAAR/zgA/v8AAAQAAP8IACj/OAAB/wgAEf84APz/AAD//wD/CAAo/zgAAf8IABH/
OAACAAAABAAA/wgAKP84AAH/CAAR/zgAAgAAAP7/AP8IACj/OAAB/wgAEf84APj/AAAGAAD/
CAAo/zgAAf8IABH/OAD9/wAA//8A/wgAKP84AAH/CAAR/zgAAwAAAAQAAP8IACj/OAAB/wgA
Ef84AAMAAAD+/wD/CAAo/zgAAf8IABH/OAD5/wAABgAA/wgAKP84AAH/CAAR/zgA/v8AAP//
AP8IACj/OAAB/wgAEf84AAQAAAAEAAD/CAAo/zgAAf8IABH/OAAEAAAA/v8A/wgAKP84AAH/
CAAR/zgA+v8AAAYAAP8IACj/OAAB/wgAEf84AP//AAD//wD/CAAo/zgAAf8IABH/OAAFAAAA
BAAA/wgAKP84AAH/CAAR/zgA//8AAAUAAP8IACj/OAAB/wgAEf84AAAAAAD//wD/CAAo/zgA
Af8IABH/OAAGAAAABAAA/wgAKP84AAH/CAAR/zgABgAAAPr/AP8IACj/OAAB/wgAEf84APz/
AAACAAD/CAAo/zgAAf8IABH/OAD+/wAABQAA/wgAKP84AAH/CAAR/zgABwAAAPr/AP8IACj/
OAAB/wgAEf84AP3/AAACAAD/CAAo/zgAAf8IABH/OAD6/wAA/f8A/wgAKP84AAH/CAAR/zgA
AAAAAAIAAP8IACj/OAAB/wgAEf84APz/AAAAAAD/CAAo/zgAAf8IABH/OAACAAAABQAA/wgA
KP84AAH/CAAR/zgA/v8AAAYAAP8IACj/OAAB/wgAEf84APv/AAD9/wD/CAAo/zgAAf8IABH/
OAABAAAAAgAA/wgAKP84AAH/CAAR/zgA/f8AAAAAAP8IACj/OAAB/wgAEf84AAMAAAAFAAD/
CAAo/zgAAf8IABH/OAD//wAABgAA/wgAKP84AAH/CAAR/zgA/P8AAP3/AP8IACj/OAAB/wgA
Ef84AAIAAAACAAD/CAAo/zgAAf8IABH/OAD+/wAAAAAA/wgAKP84AAH/CAAR/zgABAAAAAUA
AP8IACj/OAAB/wgAEf84AP7/AAADAAD/CAAo/zgAAf8IABH/OAAAAAAABgAA/wgAKP84AAH/
CAAR/zgA/f8AAP3/AP8IACj/OAAB/wgAEf84AAMAAAACAAD/CAAo/zgAAf8IABH/OAD//wAA
AAAA/wgAKP84AAH/CAAR/zgABQAAAAUAAP8IACj/OAAB/wgAEf84APn/AAD+/wD/CAAo/zgA
Af8IABH/OAD//wAAAwAA/wgAKP84AAH/CAAR/zgAAQAAAAYAAP8IACj/OAAB/wgAEf84AP7/
AAD9/wD/CAAo/zgAAf8IABH/OAAEAAAAAgAA/wgAKP84AAH/CAAR/zgABgAAAAUAAP8IACj/
OAAB/wgAEf84APr/AAD+/wD/CAAo/zgAAf8IABH/OAAAAAAAAwAA/wgAKP84AAH/CAAR/zgA
AgAAAAYAAP8IACj/OAAB/wgAEf84APv/AAD+/wD/CAAo/zgAAf8IABH/OAABAAAAAwAA/wgA
KP84AAH/CAAR/zgAAwAAAAYAAP8IACj/OAAB/wgAEf84APz/AAD+/wD/CAAo/zgAAf8IABH/
OAACAAAAAwAA/wgAKP84AAH/CAAR/zgABAAAAAYAAP8IACj/OAAB/wgAEf84AP3/AAD+/wD/
CAAo/zgAAf8IABH/OAADAAAAAwAA/wgAKP84AAH/CAAR/zgABQAAAAYAAP8IACj/OAAB/wgA
Ef84AP7/AAD+/wD/CAAo/zgAAf8IABH/OAAEAAAAAwAA/wgAKP84AAH/CAAR/zgABgAAAAYA
AP8IACj/OAAB/wgAEf84AA==]]></BinaryString>
<Color3uint8 name="Color3uint8">4288914085</Color3uint8>
<PhysicalProperties name="CustomPhysicalProperties">
<CustomPhysics>false</CustomPhysics>
</PhysicalProperties>
<float name="Elasticity">0.300000012</float>
<float name="Friction">0.5</float>
<float name="FrontParamA">-0.5</float>
<float name="FrontParamB">0.5</float>
<token name="FrontSurface">0</token>
<token name="FrontSurfaceInput">0</token>
<float name="LeftParamA">-0.5</float>
<float name="LeftParamB">0.5</float>
<token name="LeftSurface">0</token>
<token name="LeftSurfaceInput">0</token>
<bool name="Locked">true</bool>
<token name="Material">256</token>
<string name="Name">Terrain</string>
<float name="Reflectance">0</float>
<float name="RightParamA">-0.5</float>
<float name="RightParamB">0.5</float>
<token name="RightSurface">0</token>
<token name="RightSurfaceInput">0</token>
<Vector3 name="RotVelocity">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
</Vector3>
<BinaryString name="SmoothGrid"></BinaryString>
<float name="TopParamA">-0.5</float>
<float name="TopParamB">0.5</float>
<token name="TopSurface">3</token>
<token name="TopSurfaceInput">0</token>
<float name="Transparency">0</float>
<Vector3 name="Velocity">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
</Vector3>
<Color3 name="WaterColor">4278998108</Color3>
<float name="WaterTransparency">0.300000012</float>
<float name="WaterWaveSize">0.150000006</float>
<float name="WaterWaveSpeed">10</float>
<Vector3 name="size">
<X>2044</X>
<Y>252</Y>
<Z>2044</Z>
</Vector3>
</Properties>
</Item>
</Item>
<Item class="NonReplicatedCSGDictionaryService" referent="RBXDBE71218311245ACA7DEB4FA983947A1">
<Properties>
<string name="Name">NonReplicatedCSGDictionaryService</string>
</Properties>
</Item>
<Item class="CSGDictionaryService" referent="RBX7D3552EB43134AD2960D4E18677FF60E">
<Properties>
<string name="Name">CSGDictionaryService</string>
</Properties>
</Item>
<Item class="Players" referent="RBXC31EB9B193724390AECF2CCB6FD6BA06">
<Properties>
<bool name="CharacterAutoLoads">true</bool>
<int name="MaxPlayersInternal">12</int>
<string name="Name">Players</string>
<int name="PreferredPlayersInternal">0</int>
</Properties>
</Item>
<Item class="ReplicatedFirst" referent="RBX595E275F12F24649A278B92D637CA10F">
<Properties>
<string name="Name">ReplicatedFirst</string>
</Properties>
</Item>
<Item class="StarterPlayer" referent="RBXA0424C0BA4764CA89830ADAC0CB8B879">
<Properties>
<bool name="AutoJumpEnabled">true</bool>
<float name="CameraMaxZoomDistance">400</float>
<float name="CameraMinZoomDistance">0.5</float>
<token name="CameraMode">0</token>
<token name="DevCameraOcclusionMode">0</token>
<token name="DevComputerCameraMovementMode">0</token>
<token name="DevComputerMovementMode">0</token>
<token name="DevTouchCameraMovementMode">0</token>
<token name="DevTouchMovementMode">0</token>
<bool name="EnableMouseLockOption">true</bool>
<float name="HealthDisplayDistance">100</float>
<bool name="LoadCharacterAppearance">true</bool>
<string name="Name">StarterPlayer</string>
<float name="NameDisplayDistance">100</float>
</Properties>
<Item class="StarterPlayerScripts" referent="RBXA001D14ADD0A4560ABCB6971A0C6A7B8">
<Properties>
<string name="Name">StarterPlayerScripts</string>
</Properties>
</Item>
<Item class="StarterCharacterScripts" referent="RBX33D570A027E94FDE8FEF82EDD6D2E82F">
<Properties>
<string name="Name">StarterCharacterScripts</string>
</Properties>
</Item>
</Item>
<Item class="StarterPack" referent="RBX2E081228ADA24EA98F9C2EDB1CE5FDFC">
<Properties>
<string name="Name">StarterPack</string>
</Properties>
</Item>
<Item class="StarterGui" referent="RBXBF55CC33FFA0424182FF0E63319EA534">
<Properties>
<string name="Name">StarterGui</string>
<bool name="ResetPlayerGuiOnSpawn">true</bool>
<bool name="ShowDevelopmentGui">true</bool>
</Properties>
</Item>
<Item class="TeleportService" referent="RBX4381F5F0C02F4F0DA2283A85F735EEF5">
<Properties>
<string name="Name">Teleport Service</string>
</Properties>
</Item>
<Item class="SoundService" referent="RBX4810C409AE434596847E36DB4C250F34">
<Properties>
<token name="AmbientReverb">0</token>
<float name="DistanceFactor">10</float>
<float name="DopplerScale">1</float>
<string name="Name">SoundService</string>
<float name="RolloffScale">1</float>
</Properties>
</Item>
<Item class="CollectionService" referent="RBX162AA671B72645E388056E317B2DF081">
<Properties>
<string name="Name">CollectionService</string>
</Properties>
</Item>
<Item class="PhysicsService" referent="RBX89C446504B2044F49A3EB48EA42FA34E">
<Properties>
<string name="Name">PhysicsService</string>
</Properties>
</Item>
<Item class="Geometry" referent="RBX25000D7ED1554431AB1179DF24E04720">
<Properties>
<string name="Name">Geometry</string>
</Properties>
</Item>
<Item class="RenderHooksService" referent="RBX825517D9C142407BBF9ED72E82EF1DEC">
<Properties>
<string name="Name">RenderHooksService</string>
</Properties>
</Item>
<Item class="InsertService" referent="RBX35D4BFB8183E40AD8448878ECC06412B">
<Properties>
<bool name="AllowInsertFreeModels">false</bool>
<string name="Name">InsertService</string>
</Properties>
</Item>
<Item class="SocialService" referent="RBXE070386E52A747FF851539A56F98B2B0">
<Properties>
<string name="Name">SocialService</string>
</Properties>
</Item>
<Item class="GamePassService" referent="RBX90A117E698F1465D8A5E987EF2F6E638">
<Properties>
<string name="Name">GamePassService</string>
</Properties>
</Item>
<Item class="Debris" referent="RBX067D4B05C9FD431F94C9290BA6797FE9">
<Properties>
<int name="MaxItems">1000</int>
<string name="Name">Debris</string>
</Properties>
</Item>
<Item class="TimerService" referent="RBX4DEE91C72869492FA22CDCF6182D2517">
<Properties>
<string name="Name">Instance</string>
</Properties>
</Item>
<Item class="ScriptInformationProvider" referent="RBX8B53C928EE85402D86FE0E151628175F">
<Properties>
<string name="Name">Instance</string>
</Properties>
</Item>
<Item class="CookiesService" referent="RBX89B215AE3FC042D98807A824E2732DDD">
<Properties>
<string name="Name">CookiesService</string>
</Properties>
</Item>
<Item class="ContextActionService" referent="RBXAD2905268D964986A7EAEA4F155A829F">
<Properties>
<string name="Name">ContextActionService</string>
</Properties>
</Item>
<Item class="ScriptService" referent="RBX7824889C58F9463EBFA52F64AB5C4E2E">
<Properties>
<string name="Name">Instance</string>
</Properties>
</Item>
<Item class="AssetService" referent="RBX11CA345BA6854EF09DF5DDF49C277738">
<Properties>
<string name="Name">AssetService</string>
</Properties>
</Item>
<Item class="Selection" referent="RBX49F5159341DA429F81DB24927C20154D">
<Properties>
<string name="Name">Selection</string>
</Properties>
</Item>
<Item class="ServerScriptService" referent="RBX98F90543564940ED91488D3396A80374">
<Properties>
<bool name="LoadStringEnabled">false</bool>
<string name="Name">ServerScriptService</string>
</Properties>
</Item>
<Item class="ServerStorage" referent="RBX05881E5226144542911954137F2043FB">
<Properties>
<string name="Name">ServerStorage</string>
</Properties>
</Item>
<Item class="ReplicatedStorage" referent="RBX353D7C1D7ED74C8BA5EED4F0E4A0B915">
<Properties>
<string name="Name">ReplicatedStorage</string>
</Properties>
</Item>
<Item class="LuaWebService" referent="RBX0DBEAD4669F349D8AE4A3E8B96849767">
<Properties>
<string name="Name">Instance</string>
</Properties>
</Item>
<Item class="Lighting" referent="RBX5280A77C5C874B6E9B01CB0C3699B0FA">
<Properties>
<Color3 name="Ambient">4278190080</Color3>
<float name="Brightness">1</float>
<Color3 name="ColorShift_Bottom">4278190080</Color3>
<Color3 name="ColorShift_Top">4278190080</Color3>
<Color3 name="FogColor">4290822336</Color3>
<float name="FogEnd">100000</float>
<float name="FogStart">0</float>
<float name="GeographicLatitude">41.7332993</float>
<bool name="GlobalShadows">true</bool>
<string name="Name">Lighting</string>
<Color3 name="OutdoorAmbient">4286611584</Color3>
<bool name="Outlines">true</bool>
<Color3 name="ShadowColor">4289967032</Color3>
<string name="TimeOfDay">14:00:00</string>
</Properties>
</Item>
<Item class="HttpService" referent="RBXE1C8AF1816014C998094F03167472943">
<Properties>
<bool name="HttpEnabled">false</bool>
<string name="Name">HttpService</string>
</Properties>
</Item>
<Item class="GamepadService" referent="RBX3D11B627644A4B6280A4BD9C39F9A2A5">
<Properties>
<string name="Name">GamepadService</string>
</Properties>
</Item>
</roblox>

269
default_places/default.rbxl Normal file
View File

@ -0,0 +1,269 @@
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="Workspace" referent="RBX0">
<Properties>
<Ref name="CurrentCamera">RBX1</Ref>
<double name="DistributedGameTime">0</double>
<CoordinateFrame name="ModelInPrimary">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<string name="Name">Workspace</string>
<Ref name="PrimaryPart">null</Ref>
<bool name="archivable">true</bool>
</Properties>
<Item class="Camera" referent="RBX1">
<Properties>
<Ref name="CameraSubject">null</Ref>
<token name="CameraType">0</token>
<CoordinateFrame name="CoordinateFrame">
<X>34.5862312</X>
<Y>27.5593872</Y>
<Z>16.0727386</Z>
<R00>0.255434901</R00>
<R01>-0.594770193</R01>
<R02>0.762234509</R02>
<R10>7.45058149e-009</R10>
<R11>0.788388312</R11>
<R12>0.615177929</R12>
<R20>-0.96682632</R20>
<R21>-0.157137915</R21>
<R22>0.201381877</R22>
</CoordinateFrame>
<CoordinateFrame name="Focus">
<X>19.3415413</X>
<Y>15.2558289</Y>
<Z>12.0451012</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<string name="Name">Camera</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
<Item class="Part" referent="RBX2">
<Properties>
<bool name="Anchored">true</bool>
<float name="BackParamA">-0.5</float>
<float name="BackParamB">0.5</float>
<token name="BackSurface">0</token>
<token name="BackSurfaceInput">0</token>
<float name="BottomParamA">-0.5</float>
<float name="BottomParamB">0.5</float>
<token name="BottomSurface">4</token>
<token name="BottomSurfaceInput">0</token>
<int name="BrickColor">23</int>
<CoordinateFrame name="CFrame">
<X>0</X>
<Y>0.600000024</Y>
<Z>0</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<bool name="CanCollide">true</bool>
<bool name="DraggingV1">false</bool>
<float name="Elasticity">0.5</float>
<token name="FormFactor">1</token>
<float name="Friction">0.300000012</float>
<float name="FrontParamA">-0.5</float>
<float name="FrontParamB">0.5</float>
<token name="FrontSurface">0</token>
<token name="FrontSurfaceInput">0</token>
<float name="LeftParamA">-0.5</float>
<float name="LeftParamB">0.5</float>
<token name="LeftSurface">0</token>
<token name="LeftSurfaceInput">0</token>
<bool name="Locked">true</bool>
<token name="Material">256</token>
<string name="Name">Part</string>
<float name="Reflectance">0</float>
<float name="RightParamA">-0.5</float>
<float name="RightParamB">0.5</float>
<token name="RightSurface">0</token>
<token name="RightSurfaceInput">0</token>
<Vector3 name="RotVelocity">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
</Vector3>
<float name="TopParamA">-0.5</float>
<float name="TopParamB">0.5</float>
<token name="TopSurface">3</token>
<token name="TopSurfaceInput">0</token>
<float name="Transparency">0</float>
<Vector3 name="Velocity">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
</Vector3>
<bool name="archivable">true</bool>
<token name="shape">1</token>
<Vector3 name="size">
<X>64</X>
<Y>1.20000005</Y>
<Z>64</Z>
</Vector3>
</Properties>
</Item>
</Item>
<Item class="RunService" referent="RBX3">
<Properties>
<string name="Name">Run Service</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
<External>RBX4</External>
<External>RBX5</External>
<Item class="ContentProvider" referent="RBX6">
<Properties>
<string name="Name">Instance</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
<Item class="ContentFilter" referent="RBX7">
<Properties>
<string name="Name">ContentFilter</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
<Item class="KeyframeSequenceProvider" referent="RBX8">
<Properties>
<string name="Name">Instance</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
<Item class="Players" referent="RBX9">
<Properties>
<int name="MaxPlayers">12</int>
<string name="Name">Players</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
<Item class="StarterPack" referent="RBX10">
<Properties>
<string name="Name">StarterPack</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
<Item class="StarterGui" referent="RBX11">
<Properties>
<string name="Name">StarterGui</string>
<bool name="ShowDevelopmentGui">true</bool>
<bool name="archivable">true</bool>
</Properties>
</Item>
<Item class="SoundService" referent="RBX12">
<Properties>
<token name="AmbientReverb">0</token>
<float name="DistanceFactor">10</float>
<float name="DopplerScale">1</float>
<string name="Name">Soundscape</string>
<float name="RolloffScale">1</float>
<bool name="archivable">true</bool>
</Properties>
<External>RBX13</External>
<External>RBX14</External>
<External>RBX15</External>
<External>RBX16</External>
<External>RBX17</External>
<External>RBX18</External>
<External>RBX19</External>
<External>RBX20</External>
<External>RBX21</External>
<External>RBX22</External>
<External>RBX23</External>
<External>RBX24</External>
<External>RBX25</External>
<External>RBX26</External>
</Item>
<Item class="PhysicsService" referent="RBX27">
<Properties>
<string name="Name">PhysicsService</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
<Item class="BadgeService" referent="RBX28">
<Properties>
<string name="Name">BadgeService</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
<Item class="Geometry" referent="RBX29">
<Properties>
<string name="Name">Geometry</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
<External>RBX30</External>
<Item class="Debris" referent="RBX31">
<Properties>
<int name="MaxItems">300</int>
<string name="Name">Debris</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
<Item class="Timer" referent="RBX32">
<Properties>
<string name="Name">Instance</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
<Item class="ScriptInformationProvider" referent="RBX33">
<Properties>
<string name="Name">Instance</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
<External>RBX34</External>
<Item class="Selection" referent="RBX35">
<Properties>
<string name="Name">Selection</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
<External>RBX36</External>
<Item class="Lighting" referent="RBX37">
<Properties>
<Color3 name="Ambient">4286611584</Color3>
<float name="Brightness">1</float>
<Color3 name="ColorShift_Bottom">4278190080</Color3>
<Color3 name="ColorShift_Top">4278190080</Color3>
<float name="GeographicLatitude">41.7332993</float>
<string name="Name">Lighting</string>
<Color3 name="ShadowColor">4289967032</Color3>
<string name="TimeOfDay">17:50:00</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
<Item class="ChangeHistoryService" referent="RBX38">
<Properties>
<string name="Name">ChangeHistoryService</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
</roblox>

14
default_xmls/faces Normal file
View File

@ -0,0 +1,14 @@
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="Decal" referent="RBX0">
<Properties>
<token name="Face">5</token>
<string name="Name">face</string>
<float name="Shiny">20</float>
<float name="Specular">0</float>
<Content name="Texture"><url>TEXTUREURLPLACEHOLDER</url></Content>
<bool name="archivable">true</bool>
</Properties>
</Item>
</roblox>

29
default_xmls/heads Normal file
View File

@ -0,0 +1,29 @@
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="SpecialMesh" referent="RBX2ED8F01C922A40A8A1C3E74BBC31B329">
<Properties>
<token name="LODX">2</token>
<token name="LODY">2</token>
<Content name="MeshId"><url>MESHURLPLACEHOLDER</url></Content>
<token name="MeshType">5</token>
<string name="Name">Mesh</string>
<Vector3 name="Offset">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
</Vector3>
<Vector3 name="Scale">
<X>1</X>
<Y>1</Y>
<Z>1</Z>
</Vector3>
<Content name="TextureId"><null></null></Content>
<Vector3 name="VertexColor">
<X>1</X>
<Y>1</Y>
<Z>1</Z>
</Vector3>
</Properties>
</Item>
</roblox>

13
default_xmls/pants Normal file
View File

@ -0,0 +1,13 @@
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="Pants" referent="RBX0">
<Properties>
<Content name="PantsTemplate">
<url>TEXTUREURLPLACEHOLDER</url>
</Content>
<string name="Name">Pants</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
</roblox>

13
default_xmls/shirts Normal file
View File

@ -0,0 +1,13 @@
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="Shirt" referent="RBX0">
<Properties>
<Content name="ShirtTemplate">
<url>TEXTUREURLPLACEHOLDER</url>
</Content>
<string name="Name">Shirt</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
</roblox>

13
default_xmls/tshirts Normal file
View File

@ -0,0 +1,13 @@
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="ShirtGraphic" referent="RBX0">
<Properties>
<Content name="Graphic">
<url>TEXTUREURLPLACEHOLDER</url>
</Content>
<string name="Name">Shirt Graphic</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
</roblox>

1
error.json Normal file
View File

@ -0,0 +1 @@
{"errors":[{"message":"Something went wrong with the request, see response status code."}]}

View File

@ -0,0 +1,12 @@
<?php
/*
Alphaland 2021
*/
namespace Alphaland\Assets {
class Asset
{
}
}

View File

@ -0,0 +1,153 @@
<?php
/*
Alphaland 2021
*/
namespace Alphaland\Assets {
class AssetType
{
public function IsPurchasable($id)
{
switch ($id) {
}
}
public function ConvertToString(int $assetTypeId): string
{
switch ($assetTypeId) {
case 0:
return "Product";
case 1:
return "Image";
case 2:
return "T-Shirt";
case 3:
return "Audio";
case 4:
return "Mesh";
case 5:
return "Lua";
case 6:
return "HTML";
case 7:
return "Text";
case 8:
return "Hat";
case 9:
return "Place";
case 10:
return "Model";
case 11:
return "Shirt";
case 12:
return "Pants";
case 13:
return "Decal";
case 16:
return "Avatar";
case 17:
return "Head";
case 18:
return "Face";
case 19:
return "Gear";
case 21:
return "Badge";
case 22:
return "Group Emblem";
case 24:
return "Animation";
case 25:
return "Arms";
case 26:
return "Legs";
case 27:
return "Torso";
case 28:
return "Right Arm";
case 29:
return "Left Arm";
case 30:
return "Left Leg";
case 31:
return "Right Leg";
case 32:
return "Package";
case 33:
return "YouTube Video";
case 34:
return "Game Pass";
case 35:
return "App";
case 37:
return "Code";
case 38:
return "Plugin";
case 39:
return "SolidModel";
case 40:
return "MeshPart";
default:
return "Asset";
}
}
public function ConvertToStringPlural(int $assetTypeId): string
{
$string = $this->ConvertToString($assetTypeId);
switch ($string) {
case "Lua":
case "HTML":
case "Text":
case "Group Emblem":
case "App":
case "Code":
return $string;
default:
return $string . "s";
}
}
public function TypeToMaxCosmetic(int $assetTypeId): int
{
switch ($assetTypeId) {
case 8: //hat
return 5;
case 2: //tshirt
return 1;
case 11: //shirt
return 1;
case 12: //pants
return 1;
case 18: //face
return 1;
case 19: //gear
return 1;
case 17: //head
return 1;
case 32: //package
return 1;
default: //what?
return 0;
}
}
public function IsWearable(int $assetTypeId): bool
{
switch ($assetTypeId) {
case 8:
case 2:
case 11:
case 12:
case 18:
case 19:
case 17:
case 32:
return true;
default:
return false;
}
}
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace Alphaland\Common {
class HashingUtiltity
{
public static function GenerateByteHash(int $length): string
{
return bin2hex(openssl_random_pseudo_bytes($length));
}
}
}

View File

@ -0,0 +1,12 @@
<?php
/*
Alphaland 2021
*/
namespace Alphaland\Games {
class Game
{
}
}

View File

@ -0,0 +1,12 @@
<?php
/*
Alphaland 2021
*/
namespace Alphaland\Games {
class Persistence
{
}
}

View File

@ -0,0 +1,154 @@
<?php
/*
Alphaland 2021
*/
namespace Alphaland\Grid {
class RccServiceHelper
{
private string $ServiceIp;
function __construct(string $ServiceIp)
{
$this->ServiceIp = $ServiceIp;
}
private function soapCallService(string $name, array $arguments = [])
{
$soapcl = new \SoapClient($GLOBALS['RCCwsdl'], ["location" => "http://".$this->ServiceIp, "uri" => "http://roblox.com/", "exceptions" => false]);
return $soapcl->{$name}($arguments); //thanks BrentDaMage didnt know u can do this
}
private function verifyLuaValue($value) //mostly due to booleans, but maybe something will come up in the future
{
switch ($value)
{
case is_bool(json_encode($value)) || $value == 1:
return json_encode($value);
default:
return $value;
}
}
private function getLuaType($value): string //currently only supports booleans, integers and strings
{
switch ($value)
{
case $value == "true" || $value == "false": //this is so gay but php hates me
return "LUA_TBOOLEAN";
case !is_string($value) && !is_bool($value) && filter_var($value, FILTER_VALIDATE_INT):
return "LUA_TNUMBER";
default:
return "LUA_TSTRING";
}
}
private function luaArguments(array $arguments=[]) //arguments for a script being executed
{
if (!empty($arguments)) {
$luavalue = array("LuaValue"=>array());
foreach ($arguments as $argument) {
array_push($luavalue['LuaValue'], array(
"type" => $this->getLuaType($argument),
"value" => $this->verifyLuaValue($argument)
));
}
return $luavalue;
}
}
private function soapJobTemplate(string $servicename, string $jobid, int $expiration, int $category, int $cores, string $scriptname, string $script, array $arguments=[])
{
return $this->soapCallService(
$servicename,
array(
"job" => array(
"id" => $jobid,
"expirationInSeconds" => $expiration,
"category" => $category,
"cores" => $cores
),
"script" => array(
"name" => $scriptname,
"script" => $script,
"arguments" => $this->luaArguments($arguments)
)
)
);
}
public function soapGetVersion()
{
return $this->soapCallService("GetVersion");
}
public function soapHelloWorld()
{
return $this->soapCallService("HelloWorld");
}
public function soapCloseAllJobs()
{
return $this->soapCallService("CloseAllJobs");
}
public function soapCloseExpiredJobs()
{
return $this->soapCallService("CloseExpiredJobs");
}
public function soapGetAllJobsEx()
{
return $this->soapCallService("GetAllJobsEx");
}
public function soapGetStatus()
{
return $this->soapCallService("GetStatus");
}
public function soapDiagEx(string $type, string $jobid)
{
return $this->soapCallService("DiagEx", array("type" => $type, "jobID" => $jobid));
}
public function soapCloseJob(string $jobid)
{
return $this->soapCallService("CloseJob", array("jobID" => $jobid));
}
public function soapGetExpiration(string $jobid)
{
return $this->soapCallService("GetExpiration", array("jobID" => $jobid));
}
public function soapExecuteEx(string $jobid, string $scriptname, string $script, array $arguments=[])
{
return $this->soapCallService("ExecuteEx", array(
"jobID" => $jobid,
"script" => array(
"name" => $scriptname,
"script" => $script,
"arguments" => $this->luaArguments($arguments)
)
)
);
}
public function soapRenewLease(string $jobid, int $expiration)
{
return $this->soapCallService("RenewLease", array("jobID" => $jobid, "expirationInSeconds" => $expiration));
}
public function soapOpenJobEx(string $jobid, int $expiration, string $scriptname, string $script, array $arguments=[])
{
return $this->soapJobTemplate("OpenJobEx", $jobid, $expiration, 1, 3, $scriptname, $script, $arguments);
}
public function soapBatchJobEx(string $jobid, int $expiration, string $scriptname, string $script, array $arguments=[])
{
return $this->soapJobTemplate("BatchJobEx", $jobid, $expiration, 1, 3, $scriptname, $script, $arguments);
}
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace Alphaland\Moderation {
use PDO;
class UserModerationManager
{
public static function IsBanned(int $userId): bool
{
$query = UserModerationManager::$pdo->prepare("SELECT COUNT(*) FROM `user_bans` WHERE `uid` = :i AND `valid` = 1");
$query->bindParam(":i", $userId, PDO::PARAM_INT);
$query->execute();
if ($query->fetchColumn(0) > 0) return true;
return false;
}
private static PDO $pdo = $GLOBALS['pdo'];
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace Alphaland\UI {
use GdImage;
class ImageHelper
{
public static function CopyMergeImageAlpha(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_w, int $src_h, int $pct): void
{
$img = imagecreatetruecolor($src_w, $src_h);
imagecopy($img, $dst_image, 0, 0, $dst_x, $dst_y, $src_w, $src_h);
imagecopy($img, $src_image, 0, 0, $src_x, $src_y, $src_w, $src_h);
imagecopymerge($dst_image, $img, $dst_x, $dst_y, 0, 0, $src_w, $src_h, $pct);
}
public static function IsBase64PNGImage(string $base64): bool
{
$mime = finfo_buffer(finfo_open(), $base64, FILEINFO_MIME_TYPE);
if (in_array($mime, array("image/png"))) {
return true;
}
return false;
}
public static function ResizeImageFromString(int $newWidth, int $newHeight, string $targetFile, string $originalFile): bool
{
$img = imagecreatefromstring($originalFile);
$width = imagesx($img);
$height = imagesy($img);
$tmp = imagecreatetruecolor($newWidth, $newHeight);
imagealphablending($tmp, false);
imagesavealpha($tmp, true);
imagecopyresampled($tmp, $img, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
if (imagepng($tmp, "$targetFile")) {
return true;
}
return false;
}
}
}

View File

@ -0,0 +1,66 @@
<?php
/*
Alphaland 2021
*/
namespace Alphaland\Users {
use PDO;
class Activation
{
private function generateActivationCode()
{
$hash = "";
while (true) {
$hash = genHash(32);
$keycheck = $GLOBALS['pdo']->prepare("SELECT * FROM `alphaland_verification` WHERE `activationcode` = :ac");
$keycheck->bindParam(":ac", $hash, PDO::PARAM_STR);
$keycheck->execute();
if ($keycheck->rowCount() == 0) {
break;
}
}
return $hash;
}
public function getUserActivationCode(int $userid)
{
$query = $GLOBALS['pdo']->prepare("SELECT * FROM `alphaland_verification` WHERE `uid` = :uid");
$query->bindParam(":uid", $userid, PDO::PARAM_INT);
$query->execute();
if ($query->rowCount() == 1) {
return $query->fetch(PDO::FETCH_OBJ)->activationcode;
}
return false;
}
public function isUserActivated(int $userid)
{
$query = $GLOBALS['pdo']->prepare("SELECT * FROM `alphaland_verification` WHERE `isactivated` = 1 AND `uid` = :uid");
$query->bindParam(":uid", $userid, PDO::PARAM_INT);
$query->execute();
if ($query->rowCount() > 0) {
return true;
}
return false;
}
public function setupUserActivation(int $userid) //this should be ran when the user first signs up
{
if (!$this->isUserActivated($userid)) {
$activationcode = $this->generateActivationCode();
$n = $GLOBALS['pdo']->prepare("INSERT INTO `alphaland_verification`(`activationcode`,`uid`) VALUES(:ac, :userid)");
$n->bindParam(":ac", $activationcode, PDO::PARAM_STR);
$n->bindParam(":userid", $userid, PDO::PARAM_INT);
$n->execute();
return true;
}
return false;
}
}
}

View File

@ -0,0 +1,133 @@
<?php
namespace Alphaland\Users {
use Alphaland\Moderation\UserModerationManager;
use Alphaland\Web\WebContextManager;
use PDO;
class User
{
public int $ID = -1;
public string $Name;
public UserRank $Rank = UserRank::Visitor;
public int $Currency = 0;
public int $SessionCookieID = 0;
public bool $IsLoggedIn = false;
function __construct()
{
// TODO: Potential shared constant for the cookie's name?
if (isset($_COOKIE['token']))
$this->ValidateToken($_COOKIE['token']);
}
// RoleSet helpers
public function IsOwner()
{
return $this->Rank === UserRank::Owner;
}
public function IsAdministrator()
{
return $this->Rank === UserRank::Administrator || $this->Rank === UserRank::Owner;
}
public function IsStaff()
{
return $this->Rank === UserRank::Administrator || $this->Rank === UserRank::Moderator || $this->Rank === UserRank::Owner;
}
public function UpdateLastSeen()
{
if (!UserModerationManager::IsBanned($this->ID)) {
$query = $this->pdo->prepare("UPDATE `users` SET `lastseen` = UNIX_TIMESTAMP() WHERE `id` = :id");
$query->bindParam(":id", $this->ID, PDO::PARAM_INT);
$query->execute();
}
}
public function UpdateDailyTime(int $dailyTime)
{
if (!UserModerationManager::IsBanned($this->ID)) {
if (($dailyTime + User::SecondsInDays) < time() || $dailyTime == 0) {
// it has been a day or this is their first collection.
$query = $this->pdo->prepare("UPDATE `users` SET `dailytime` = UNIX_TIMESTAMP(), `currency` = (`currency` + 20) WHERE `id` = :id");
$query->bindParam(":id", $this->ID, PDO::PARAM_INT);
$query->execute();
}
}
}
public function UpdateIpAddress()
{
$ip = WebContextManager::GetCurrentIPAddress();
$query = $this->pdo->prepare("UPDATE `users` SET `ip` = :ip WHERE `id` = :id");
$query->bindParam(":ip", $ip, PDO::PARAM_STR);
$query->bindParam(":id", $this->ID, PDO::PARAM_INT);
$query->execute();
}
public function ValidateToken(string $token): bool
{
$query = $this->pdo->prepare("SELECT * FROM `users` WHERE `id` = :id");
$query->bindParam(":tk", $token, PDO::PARAM_STR);
$query->execute();
if ($query->rowCount() > 0) {
return $this->ValidateTokenInternal($query->fetch(PDO::FETCH_OBJ));
}
// No valid session found.
setcookie("token", null, time(), "/");
return false;
}
public function Logout()
{
if ($this->IsLoggedIn) {
$query = $this->pdo->prepare("UPDATE `sessions` SET `valid` = 0 WHERE `id` = :id");
$query->bindParam(":id", $this->SessionCookieID, PDO::PARAM_INT);
$query->execute();
}
}
private function ValidateTokenInternal($session): bool
{
$query = $this->pdo->prepare("SELECT * FROM users WHERE id = :id");
$query->bindParam(":id", $session->uid, PDO::PARAM_INT);
$query->execute();
if ($query->rowCount() > 0) {
$userInfo = $query->fetch(PDO::FETCH_OBJ);
$this->ConstructSelf($session, $userInfo);
$this->UpdateLastSeen();
$this->UpdateIpAddress();
$this->UpdateDailyTime($userInfo->dailytime);
return true;
}
// No user info found.
setcookie("token", null, time(), "/");
return false;
}
private function ConstructSelf($session, $userInfo)
{
// Session
$this->IsLoggedIn = true;
$this->ID = $session->uid;
$this->SessionCookieID = $session->id;
// UserInfo
$this->Name = $userInfo->username;
$this->Rank = UserRank::FromInt($userInfo->rank);
$this->Currency = $userInfo->currency;
}
private PDO $pdo = $GLOBALS['pdo'];
private const $SecondsInDays = 86400;
}
}

View File

@ -0,0 +1,60 @@
<?php
/**
* File Name: UserRank.php
* Written By: Nikita Petko
* Description: Rank of a user I suppose
*/
namespace Alphaland\Users {
/**
* Refers to the mock RoleSet of a user in the DataBase.
* The abstract class here is apparently how you do Enums in PHP.
*/
abstract class UserRank
{
/**
* The user is a visitor to the site.
*/
const Visitor = -1;
/**
* The user is a regular member that signed up.
*/
const Member = 0;
/**
* The user has more privilages
*/
const Moderator = 1;
/**
* Too lazy to doc
*/
const Administrator = 2;
/**
* Too lazy to doc
*/
const Owner = 3;
public static function FromInt(int $id)
{
switch ($id) {
case 0:
return UserRank::Member;
case 1:
return UserRank::Moderator;
case 2:
return UserRank::Administrator;
case 3:
return UserRank::Owner;
case -1:
default:
return UserRank::Visitor;
}
}
}
}

View File

@ -0,0 +1,53 @@
<?php
namespace Alphaland\Web {
use Alphaland\Users\User;
use PDO;
class WebContextManager
{
public static function GetCurrentIPAddress(): string
{
return (isset($_SERVER["HTTP_CF_CONNECTING_IP"]) ? $_SERVER["HTTP_CF_CONNECTING_IP"] : $_SERVER['REMOTE_ADDR']);
}
public static function IsUnderMaintenance(): bool
{
$query = WebContextManager::$pdo->prepare("SELECT * FROM `websettings` WHERE `maintenance` = 1");
$query->execute();
if ($query->rowCount() > 0)
{
return true;
}
return false;
}
public static function CanBypassMaintenance()
{
// Wouldn't really be a bypass per say, but you know, reusing existing code is better than
// copying already existing code.
if (!WebContextManager::IsUnderMaintenance()) return true;
if (
!WebContextManager::CurrentUser->IsAdministrator()
&& !WebContextManager::IsCurrentIpAddressWhitelisted()
) return false;
return true;
}
public static function IsCurrentIpAddressWhitelisted()
{
$currentIp = WebContextManager::GetCurrentIPAddress();
$ipWhitelist = []; // query from db
return in_array($currentIp, $ipWhitelist);
}
private static PDO $pdo = $GLOBALS['pdo'];
public static const $CurrentUser = new User();
}
}

197
globals/config.php Normal file
View File

@ -0,0 +1,197 @@
<?php
/*
Alphaland 2021 site configuration
This is extremely sensitive.
*/
try
{
//php config
ini_set("display_errors", "Off");
ignore_user_abort(true);
//PDO
$pdoOptions = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_PERSISTENT => true
);
//host //db name //db user //db password //options
$pdo = new PDO("mysql:host=localhost;dbname=alphalanddatabase", "aa9205c5b776b2368833bec1e8b34e1c", "68adae776e087fb1b34baf439710cf94", $pdoOptions);
//general vars
$cssversion = "3.02"; //update this after updating CSS, this will re-cache the latest css for users
$siteName = "Alphaland"; //site name
$domain = "alphaland.cc";
$url = "https://www.".$domain; //site URL
$ws = $pdo->query("SELECT * FROM websettings WHERE id = 1")->fetch(PDO::FETCH_OBJ); //websettings
$clientUserAgent = "Roblox/WinInet";
$ROBLOXAssetAPI = "https://assetdelivery.roblox.com/v1/asset/?id=";
$ROBLOXProductInfoAPI = "https://api.roblox.com/marketplace/productinfo?assetId=";
//default character hashes
$defaultOutfitHash = "e335382cb0ef996df9053df58adcbe95"; //default render hash for characters
$defaultHeadshotHash = "fb5d52c08aa538483647373c5a20fd73"; //default headshot render for characters
//cdn urls
$renderCDN = "https://trcdn.alphaland.cc"; //endpoint for renders
$assetCDN = "https://acdn.alphaland.cc"; //endpoint for assets
$thumbnailCDN = "https://tcdn.alphaland.cc"; //endpoint for thumbnails
//cdn paths
$renderCDNPath = "C:/Webserver/nginx/Alphaland/html_renders_cdn/"; //path to where renders are stored
$thumbnailCDNPath = "C:/Webserver/nginx/Alphaland/html_thumbs_cdn/"; //path to where thumbnails are stored
$assetCDNPath = "C:/Webserver/nginx/Alphaland/html_assets_cdn/"; //path to where assets are stored
//lua script paths
$avatarthumbnailscript = "C:/Webserver/nginx/Alphaland/luascripts/thumbnails/AvatarScript.lua";
$facethumbnailscript = "C:/Webserver/nginx/Alphaland/luascripts/thumbnails/FaceScript.lua";
$hatthumbnailscript = "C:/Webserver/nginx/Alphaland/luascripts/thumbnails/HatScript.lua";
$tshirtthumbnailscript = "C:/Webserver/nginx/Alphaland/luascripts/thumbnails/TShirtScript.lua";
$shirtthumbnailscript = "C:/Webserver/nginx/Alphaland/luascripts/thumbnails/ShirtScript.lua";
$pantsthumbnailscript = "C:/Webserver/nginx/Alphaland/luascripts/thumbnails/PantsScript.lua";
$headthumbnailscript = "C:/Webserver/nginx/Alphaland/luascripts/thumbnails/HeadScript.lua";
$placethumbnailscript = "C:/Webserver/nginx/Alphaland/luascripts/thumbnails/PlaceScript.lua";
$modelthumbnailscript = "C:/Webserver/nginx/Alphaland/luascripts/thumbnails/ModelScript.lua";
$gearthumbnailscript = "C:/Webserver/nginx/Alphaland/luascripts/thumbnails/GearScript.lua";
$avatarcloseupthumbnailscript = "C:/Webserver/nginx/Alphaland/luascripts/thumbnails/AvatarCloseupScript.lua";
$meshthumbnailscript = "C:/Webserver/nginx/Alphaland/luascripts/thumbnails/MeshScript.lua";
$packagescript = "C:/Webserver/nginx/Alphaland/luascripts/thumbnails/PackageScript.lua";
$gameserverscript = "C:/Webserver/nginx/Alphaland/luascripts/game/gameserver.lua";
//soap paths
$RCCwsdl = "C:/Webserver/nginx/Alphaland/RCCService.wsdl"; //wsdl path for SOAP
//misc paths
$setupHtmlPath = "C:/Webserver/nginx/Alphaland/html_setup/";
$defaultPlacesPath = "C:/Webserver/nginx/Alphaland/default_places/"; //path to where the default places are stored
$defaultPbsPlacesPath = "C:/Webserver/nginx/Alphaland/default_pbs_places/"; //path to where the default pbs places are stored
$defaultXmlsPath = "C:/Webserver/nginx/Alphaland/default_xmls/"; //path to where the default xmls stored
$privateKeyPath = "C:/Webserver/nginx/Alphaland/AlphalandRawKey.txt"; //path to where the private key is stored
//machine ip's
$gameMachine = "167.114.96.92"; //IP address of the machine that runs gameservers
$renderMachine = "192.168.1.234"; //IP address of the machine that renders thumbnails
//arbiter ip's
$gamesArbiter = "192.168.1.169:64989"; //IP address/port of the Arbiter running on the gameserver machine
$thumbnailArbiter = $renderMachine.":64989"; //IP address/port of the Arbiter running on the render machine
//autoloader include
require 'C:\Users\Administrator\vendor\autoload.php';
//mail includes
require 'C:\Users\Administrator\vendor\phpmailer\phpmailer\src\Exception.php';
require 'C:\Users\Administrator\vendor\phpmailer\phpmailer\src\PHPMailer.php';
require 'C:\Users\Administrator\vendor\phpmailer\phpmailer\src\SMTP.php';
//alphaland specfic dependencies
include "C:/Webserver/nginx/Alphaland/globals/Dependencies/Users/Activation.php";
//mailer
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
$mail->IsSMTP();
$mail->SMTPAuth = TRUE;
$mail->SMTPSecure = "tls";
$mail->Port = 587;
$mail->Host = "smtp.gmail.com";
$mail->Username = "alphalandtemp@gmail.com"; //google for now (easy and free)
$mail->Password = "117A7AE7CE40674453E00492CB699F54";
//cloudflare
$cloudflareheader = array(
"Content-Type: application/json",
"X-Auth-Email: superativeroblox@gmail.com",
"X-Auth-Key: 06ea819593bb6d038c8d49808c0f0f200124b"
);
//more includes
require_once 'functions.php';
require_once 'userauth.php';
//redirects
if (!commandLine() && //is not executed from cmd line
!RCCHeaderEnvironment(true)) //is not an authenticated rcc
{
$accesseddomain = $_SERVER['SERVER_NAME'];
$accesseddirectory = $_SERVER['PHP_SELF'];
if ($accesseddomain == "www.".$domain && //if the domain the user is visiting www
$_SERVER['HTTP_USER_AGENT'] != $clientUserAgent) { //is not client user agent
forceHttpsCloudflare();
}
$activated = new Alphaland\Users\Activation();
$activated = $activated->isUserActivated($GLOBALS['user']->id);
$maintenance = checkIfUnderMaintenance();
$banned = checkIfBanned($GLOBALS['user']->id);
if ($maintenance) { //maintenance redirect
if ($accesseddirectory != "/maintenance.php") {
redirect($url . "/maintenance");
}
}
if ($banned && !$maintenance) { //ban redirect
if ($accesseddirectory != "/ban.php" &&
$accesseddirectory != "/logout.php") {
redirect($url . "/ban");
}
}
if ($GLOBALS['user']->logged_in && !$activated && !$banned && !$maintenance) { //activation redirect
if ($accesseddirectory != "/activate.php" &&
$accesseddirectory != "/logout.php") {
redirect($url . "/activate");
}
}
//pages accessible to users who aren't logged in
if (!$GLOBALS['user']->logged_in) { //not logged in
if ($accesseddomain == "www.".$domain) { //www
if ($accesseddirectory != "/index.php" &&
$accesseddirectory != "/login/index.php" &&
$accesseddirectory != "/login/forgotpassword.php" &&
$accesseddirectory != "/register.php" &&
$accesseddirectory != "/verifyemail.php" &&
$accesseddirectory != "/maintenance.php" &&
$accesseddirectory != "/noJS.php" &&
$accesseddirectory != "/ban.php" &&
$accesseddirectory != "/404.php" &&
$accesseddirectory != "/Game/Negotiate.ashx" &&
$accesseddirectory != "/asset/index.php" &&
$accesseddirectory != "/settings/resetpassword.php" &&
//$accesseddirectory != "/Game/Join.ashx" &&
//$accesseddirectory != "/Game/PlaceLauncher.ashx" &&
$accesseddirectory != "/secret/localtesting.php") { //for local client testing, doesn't contain anything sensitive
redirect($url);
}
}
else if ($accesseddomain == "api.".$domain) { //api
if ($accesseddirectory != "/logo.php" &&
$accesseddirectory != "/moderation/v2/filtertext.php") {
redirect($url);
}
}
else if ($accesseddomain == "data.".$domain) { //data
if ($accesseddirectory != "/Error/Dmp.ashx") {
redirect($url);
}
}
else if ($accesseddomain == "setup.".$domain) { //setup
//do nothing (we arent restricting on this subdomain)
}
else if ($accesseddomain == "clientsettings.api.".$domain) { //clientsettings
//do nothing (we arent restricting on this subdomain)
} else {
redirect($url);
}
}
}
}
catch (Exception $e)
{
die("Alphaland is currently unavailable.");
}

6973
globals/functions.php Normal file

File diff suppressed because it is too large Load Diff

71
globals/pageHandler.php Normal file
View File

@ -0,0 +1,71 @@
<?php
/*
Alphaland 2021
Easy utility for pages
*/
class page_handler {
public $siteName = "Alphaland";
public $sheader;
public $pagetitle;
public $navbar;
public $body;
public $bodyStructure;
public $footer;
public $studio;
public $addheader;
public $pageStructure = '<!DOCTYPE html>
<html>
<head>
<noscript>
<meta http-equiv="Refresh" content="0; URL=noJS" />
</noscript>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>%s</title>
%s
</head>
<body>
%s
%s
%s
</body>
</html>';
function pageTitle($string) {
$this->pagetitle .= (string)$string." | ".$this->siteName;
}
function changebody($string) {
$this->bodyStructure .= (string)$string;
}
function addHeader($string) {
if($this->addheader === null) {
$this->addheader = "
";
}
$this->addheader .= (string)$string;
}
function output() {
if($this->sheader === null) {
$this->sheader = getCSS($this->studio);
}
if($this->pagetitle === null) {
$this->pagetitle = $GLOBALS['siteName'];
}
if($this->navbar === null) {
$this->navbar = getNav();
}
if($this->footer === null) {
$this->footer = getFooter();
}
echo sprintf(
$this->pageStructure,
$this->pagetitle,
$this->sheader.$this->addheader,
$this->navbar,
$this->body,
$this->footer
);
}
}

114
globals/userauth.php Normal file
View File

@ -0,0 +1,114 @@
<?php
/*
Alphaland 2021
User class
*/
class user {
public $id = -1;
public $name = "";
public $rank = -1; // -1 = visitor, 0 = member, 1 = mod, 2 = admin, 3 = owner
public $currency = -1;
public $sessionCookieID = 0;
public $logged_in = false;
function __construct() {
if(isset($_COOKIE['token'])) { $this->checkIfTokenValid($_COOKIE['token']); }
}
function isOwner() {
if ($this->rank == 3) {
return true;
}
return false;
}
function isAdmin() {
if($this->rank == 2 || $this->rank == 3) {
return true;
}
return false;
}
function isStaff() {
if($this->rank == 1 || $this->rank == 2 || $this->rank == 3) {
return true;
}
return false;
}
function checkIfTokenValid($token) {
$check = $GLOBALS['pdo']->prepare("SELECT * FROM sessions WHERE token = :tk AND valid = 1");
$check->bindParam(":tk", $token, PDO::PARAM_STR);
$check->execute();
if($check->rowCount() > 0) {
$info = $check->fetch(PDO::FETCH_OBJ);
$userIP = getIP();
//if(($info->whenCreated + (86400 * 30)) > time()) { //Tokens should only last 30 days
$userInfo = $GLOBALS['pdo']->prepare("SELECT * FROM users WHERE id = :id");
$userInfo->bindParam(":id", $info->uid, PDO::PARAM_INT);
$userInfo->execute();
if($userInfo->rowCount() > 0) {
$userInfo = $userInfo->fetch(PDO::FETCH_OBJ);
//session info
$this->logged_in = true;
$this->id = $info->uid;
$this->sessionCookieID = $info->id;
// ...
//user info
$this->name = $userInfo->username;
$this->rank = $userInfo->rank;
$this->currency = $userInfo->currency;
// ..
//activation stuff
$activated = new Alphaland\Users\Activation();
$activated = $activated->isUserActivated($this->id);
if (!banned($this->id))
{
//update token interval
$updateLastSeen = $GLOBALS['pdo']->prepare("UPDATE users SET lastseen = UNIX_TIMESTAMP() WHERE id = :id");
$updateLastSeen->bindParam(":id", $this->id, PDO::PARAM_INT);
$updateLastSeen->execute();
}
//update user's ip
$updateip = $GLOBALS['pdo']->prepare("UPDATE users SET ip = :ip WHERE id = :id");
$updateip->bindParam(":ip", $userIP, PDO::PARAM_STR);
$updateip->bindParam(":id", $info->uid, PDO::PARAM_INT);
$updateip->execute();
if ($activated && !banned($this->id))
{
//reward currency daily
if (($userInfo->dailytime + (86400 * 1)) < time() || $userInfo->dailytime == 0) //its been a day or first time
{
$updateDaily = $GLOBALS['pdo']->prepare("UPDATE users SET dailytime = UNIX_TIMESTAMP(), currency = (currency + 20) WHERE id = :id");
$updateDaily->bindParam(":id", $this->id, PDO::PARAM_INT);
$updateDaily->execute();
}
}
return true;
}
//}
}
//invalid token, set the token to null
setcookie("token", null, time(), "/");
return false;
}
function logout() {
if($this->logged_in) {
$logout = $GLOBALS['pdo']->prepare("UPDATE sessions SET valid = 0 WHERE id = :id");
$logout->bindParam(":id", $this->sessionCookieID, PDO::PARAM_INT);
$logout->execute();
}
}
}
$user = new user();

24
html/404.php Normal file
View File

@ -0,0 +1,24 @@
<?php
$body = <<<EOT
<div class="container-fluid">
<div class="container">
<div class="card">
<div class="card-body text-center">
<img style="width: 15rem;" src="https://api.alphaland.cc/logo">
<h2 class="mt-3">404 | Page not found</h2>
<hr>
<a onclick="javascript:history.back()"><button class="btn btn-danger">Back</button></a><h> </h><a onclick="location.href = '/';""><button class="btn btn-danger">Home</button></a>
</div>
</div>
</div>
</div>
EOT;
pageHandler();
if(!isLoggedIn())
{
$ph->footer = ""; //no footer for no login
}
$ph->body = $body;
$ph->output();

38
html/Game/AdminScript.php Normal file
View File

@ -0,0 +1,38 @@
<?php
//stuff for staff will be handled here
RCCHeaderEnvironment(); //secure for RCC access only
/*
local GUI = Instance.new("BillboardGui")
local Text = Instance.new("TextLabel")
GUI.StudsOffset = Vector3.new(0,2,0)
GUI.Size = UDim2.new(4,0,1,0)
Text.BackgroundTransparency = 1
Text.TextScaled = true
Text.TextColor3 = Color3.new(255, 0, 0)
Text.FontSize = 'Size14'
Text.Size = UDim2.new(1,0,1,0)
Text.Text = "Administrator"
GUI.Parent = plr.Character.Head
Text.Parent = GUI
*/
$script = <<<EOF
game.Players.PlayerAdded:Connect(function(plr)
plr.CharacterAdded:wait()
if plr.Name == "Astrologies" then
tool = game:GetService("InsertService"):LoadAsset(1630):GetChildren()[1]
tool.Parent = plr.StarterGear
plr.StarterGear.BanHammer:Clone().Parent = plr.Backpack
end
end)
EOF;
echo signData($script); //return the signature+script

21
html/Game/AreFriendss.php Normal file
View File

@ -0,0 +1,21 @@
<?php
header("Cache-Control: no-cache, no-store");
header("Pragma: no-cache");
header("Expires: -1");
header("Last-Modified: " . gmdate("D, d M Y H:i:s T") . " GMT");
$userId = $_GET['userId'];
$otherUserIds = $_GET['otherUserIds'];
$users = "";
foreach ($otherUserIds as $id)
{
if (friendsWithUser($userId, $id))
{
$users = $users . $id . ",";
}
}
//$userids = substr($users, 0, -1); //remove last comma pog
echo "," . $users;

23
html/Game/ClientPing.ashx Normal file
View File

@ -0,0 +1,23 @@
<?php
if ($_SERVER['HTTP_USER_AGENT'] != $GLOBALS['clientUserAgent']) //user agent restricted
{
die("Invalid request");
}
$userid = (int)$_GET['UserID'];
$placeid = (int)$_GET['PlaceID'];
$p = $pdo->prepare("SELECT * FROM game_presence WHERE uid = :u AND placeid = :p");
$p->bindParam(":u", $userid, PDO::PARAM_INT);
$p->bindParam(":p", $placeid, PDO::PARAM_INT);
$p->execute();
if ($p->rowCount() > 0)
{
//presence valid, update the lastPing
$u = $pdo->prepare("UPDATE game_presence SET lastPing = UNIX_TIMESTAMP() WHERE uid = :u AND placeid = :p");
$u->bindParam(":u", $userid, PDO::PARAM_INT);
$u->bindParam(":p", $placeid, PDO::PARAM_INT);
$u->execute();
}

View File

@ -0,0 +1,144 @@
<?php
//the design choice here was to tie in clientpresence with recently played and visits and make it fully server-sided besides the client pings
RCCHeaderEnvironment();
$action = (string)$_GET['action'];
$userid = (int)$_GET['UserID'];
$placeid = (int)$_GET['PlaceID'];
$jobid = (string)$_GET['JobID'];
$isteleport = (bool)$_GET['IsTeleport'];
function BadRequest()
{
die(http_response_code(400));
}
if (!$action || !$userid || !$placeid)
{
BadRequest();
}
if (!userExists($userid))
{
BadRequest();
}
$p = $pdo->prepare("SELECT * FROM game_launch_tokens WHERE uid = :u AND jobid = :jid");
$p->bindParam(":u", $userid, PDO::PARAM_INT);
$p->bindParam(":jid", $jobid, PDO::PARAM_INT);
$p->execute();
if ($p->rowCount() == 0) //no hits, so not valid user
{
BadRequest();
}
if ($action == "disconnect")
{
$u = $pdo->prepare("DELETE FROM game_presence WHERE uid = :i");
$u->bindParam(":i", $userid, PDO::PARAM_INT);
$u->execute();
}
else if ($action == "connect")
{
//check if user already has a presence, delete if exists
$p = $pdo->prepare("SELECT * FROM game_presence WHERE uid = :u");
$p->bindParam(":u", $userid, PDO::PARAM_INT);
$p->execute();
if ($p->rowCount() > 0)
{
$u = $pdo->prepare("DELETE FROM game_presence WHERE uid = :i");
$u->bindParam(":i", $userid, PDO::PARAM_INT);
$u->execute();
}
// ...
//create player presence (pass in the current servers job id for following functionality)
$g = $pdo->prepare("INSERT INTO game_presence(uid,placeid,jobid,whenJoined,lastPing) VALUES(:u,:p,:j,UNIX_TIMESTAMP(),UNIX_TIMESTAMP())");
$g->bindParam(":u", $userid, PDO::PARAM_INT);
$g->bindParam(":p", $placeid, PDO::PARAM_INT);
$g->bindParam(":j", $jobid, PDO::PARAM_STR);
$g->execute();
// ...
//remove them from queue (once presence is created above, placelauncher will detect playercount correctly. should be very rare for two people to get in a single slot)
removePlayerFromQueue($userid);
//update or create player recently played (TODO: restrict to 4 database entries to save space)
$checkforrecent = $pdo->prepare("SELECT * FROM game_recents WHERE uid = :i AND gid = :g");
$checkforrecent->bindParam(":i", $userid, PDO::PARAM_INT);
$checkforrecent->bindParam(":g", $placeid, PDO::PARAM_INT);
$checkforrecent->execute();
if ($checkforrecent->rowCount() > 0)
{
//update recently played
$setgamerecent = $pdo->prepare("UPDATE game_recents SET whenPlayed = UNIX_TIMESTAMP() WHERE uid = :u AND gid = :g");
$setgamerecent->bindParam(":u", $userid, PDO::PARAM_INT);
$setgamerecent->bindParam(":g", $placeid, PDO::PARAM_INT);
$setgamerecent->execute();
//...
}
else
{
//create recently played
$setgamerecent = $pdo->prepare("INSERT INTO game_recents(uid,gid,whenPlayed) VALUES(:u,:g,UNIX_TIMESTAMP())");
$setgamerecent->bindParam(":u", $userid, PDO::PARAM_INT);
$setgamerecent->bindParam(":g", $placeid, PDO::PARAM_INT);
$setgamerecent->execute();
//...
}
// ...
//place visit
$new_visit = false;
$visit = $pdo->prepare("SELECT * FROM game_unique_visit WHERE uid = :i AND gid = :g");
$visit->bindParam(":i", $userid, PDO::PARAM_INT);
$visit->bindParam(":g", $placeid, PDO::PARAM_INT);
$visit->execute();
if ($visit->rowCount() > 0) //we got a hit
{
$info = $visit->fetch(PDO::FETCH_OBJ);
if(($info->visited + (86400 * 1)) > time()) //one day
{
return;
}
else //no visit to the game today
{
$setuniquevisit = $pdo->prepare("UPDATE game_unique_visit SET visited = :t WHERE uid = :u AND gid = :g");
$setuniquevisit->bindParam(":u", $userid, PDO::PARAM_INT);
$setuniquevisit->bindParam(":g", $placeid, PDO::PARAM_INT);
$setuniquevisit->bindParam(":t", time(), PDO::PARAM_INT);
$setuniquevisit->execute();
$new_visit = true;
}
}
else
{
$setuniquevisit = $pdo->prepare("INSERT INTO game_unique_visit(uid,gid,visited) VALUES(:u,:g,:t)");
$setuniquevisit->bindParam(":u", $userid, PDO::PARAM_INT);
$setuniquevisit->bindParam(":g", $placeid, PDO::PARAM_INT);
$setuniquevisit->bindParam(":t", time(), PDO::PARAM_INT);
$setuniquevisit->execute();
$new_visit = true;
}
if (new_visit)
{
$setgamevisit = $pdo->prepare("UPDATE assets SET Visited = (Visited + 1) WHERE id = :g");
$setgamevisit->bindParam(":g", $placeid, PDO::PARAM_INT);
$setgamevisit->execute();
}
// ...
}
else
{
BadRequest(); //something RCC will show if the request is failing for some reason
}

View File

@ -0,0 +1,9 @@
<?php
//header('Content-Type: application/json');
header("Cache-Control: no-cache, no-store");
header("Pragma: no-cache");
header("Expires: -1");
header("Last-Modified: " . gmdate("D, d M Y H:i:s T") . " GMT");
echo $user->id;

98
html/Game/Join.ashx Normal file
View File

@ -0,0 +1,98 @@
<?php
/*
Alphaland 2021
Very messy but will clean up
*/
header("Content-Type: text/plain");
$token = (string)$_GET['ticket'];
$local = $_GET['local'];
if ($local)
{
$joinparams = json_encode(array(
"MachineAddress" => "localhost",
"ServerPort" => "65535",
"ClientPort" => 0,
"UserName" => "Astrologies",
"UserId" => 2,
"CreatorId" => 2,
"CreatorTypeEnum" => "User",
"ChatStyle" => "ClassicAndBubble",
"PlaceId" => 186,
"CharacterAppearance" => "https://api.alphaland.cc/users/avatar-accoutrements?userId=2",
//"IsRobloxPlace" => true,
"ClientTicket" => "111",
"BaseUrl" => $url . "/",
"PingUrl" => $url . "",
"PingInterval" => 45
), JSON_UNESCAPED_SLASHES);
die(signData($joinparams));
}
if ($_SERVER['HTTP_USER_AGENT'] == $GLOBALS['clientUserAgent']) //user agent restricted
{
$q = $pdo->prepare("SELECT * FROM game_launch_tokens WHERE token = :i AND (whenCreated + 20) > UNIX_TIMESTAMP()");
$q->bindParam(":i", $token, PDO::PARAM_STR);
$q->execute();
if($q->rowCount() > 0)
{
$sInfo = $q->fetch(PDO::FETCH_OBJ);
$siq = $pdo->prepare("SELECT * FROM open_servers WHERE jobid = :i");
$siq->bindParam(":i", $sInfo->jobid, PDO::PARAM_INT);
$siq->execute();
$serverInfo = $siq->fetch(PDO::FETCH_OBJ);
$gameInfo = getAssetInfo($serverInfo->gameID);
if (userAccessToGame($gameInfo->id, $sInfo->uid))
{
$jobid = $sInfo->jobid;
$placeid = $gameInfo->id;
$userid = $sInfo->uid;
$username = getUsername($userid);
$characterappearance = "https://api.alphaland.cc/users/avatar-accoutrements?userId=" . $userid;
$accountage = round((time()-userInfo($userid)->joindate)/86400);
$joinparams = json_encode(array(
"ClientPort" => 0,
"MachineAddress" => $serverInfo->ip,
"ServerPort" => $serverInfo->port,
"PingUrl" => $url . "/Game/ClientPing.ashx?UserID=" . $userid . "&PlaceID=" . $placeid,
"PingInterval" => 45,
"UserName" => $username,
"SeleniumTestMode" => false, //always false, dont need this
"UserId" => $userid,
"SuperSafeChat" => false, //always false, dont need this
"CharacterAppearance" => $characterappearance,
"ClientTicket" => generateClientTicket($userid, $accountage, $username, $characterappearance, $jobid), //generate epic clientticket
"GameId" => '00000000-0000-0000-0000-000000000000', //not set rn?
"PlaceId" => $placeid,
"BaseUrl" => $url . "/",
"ChatStyle" => "ClassicAndBubble", //TODO: make an option for this
"VendorId" => 0, //0, dont need this rn?
"ScreenShotInfo" => "", //blank, dont need this rn?
"VideoInfo" => "", //blank, dont need this rn?
"CreatorId" => $gameInfo->CreatorId,
"CreatorTypeEnum" => "User", //only player places, dont need this
"MembershipType" => "None", //no memberships rn
"AccountAge" => $accountage,
"CookieStoreEnabled" => false, //always false, dont need this
"IsRobloxPlace" => false, //dont this this rn?
"GenerateTeleportJoin" => false, //dont need this rn?
"IsUnknownOrUnder13" => false, //dont need this rn?
"SessionId" => "", //blank, dont need this rn?
"DataCenterId" => 0, //0, dont need this rn?
"UniverseId" => 0, //0, dont need this rn?
"BrowserTrackerId" => "" //blank, dont need this rn?
), JSON_UNESCAPED_SLASHES);
die(signData($joinparams));
}
}
}
die(http_response_code(400));

16
html/Game/KillServer.php Normal file
View File

@ -0,0 +1,16 @@
<?php
RCCHeaderEnvironment();
$jobID = (string)$_GET['jobid'];
$q = $pdo->prepare("SELECT * FROM open_servers WHERE jobid = :i AND status != 2");
$q->bindParam(":i", $jobID, PDO::PARAM_INT);
$q->execute();
if($q->rowCount() > 0) {
$sInfo = $q->fetch(PDO::FETCH_OBJ);
$u = $pdo->prepare("UPDATE open_servers SET status = 2, whenDied = UNIX_TIMESTAMP() WHERE id = :i");
$u->bindParam(":i", $sInfo->id, PDO::PARAM_INT);
$u->execute();
}

View File

@ -0,0 +1,2 @@
<?php
require '../../bweb/bweb.php';

53
html/Game/Negotiate.ashx Normal file
View File

@ -0,0 +1,53 @@
<?php
/*
This is used on the client with a provided auth_ticket to authenticate the user
A cookie is set inside the client (IE)
TODO: Clean up
*/
header("Cache-Control: no-cache");
header("Pragma: no-cache");
header("Expires: -1");
header("Last-Modified: " . gmdate("D, d M Y H:i:s T") . " GMT");
if ($_SERVER['HTTP_USER_AGENT'] != "Roblox/WinInet") //user agent restricted
{
die("Invalid request");
}
$token = (string)$_GET['suggest'];
$currenttoken = $GLOBALS['pdo']->prepare("SELECT * FROM user_auth_tickets WHERE token = :t");
$currenttoken->bindParam(":t", $token, PDO::PARAM_STR);
$currenttoken->execute();
if ($currenttoken->rowCount() > 0)
{
$aInfo = $currenttoken->fetch(PDO::FETCH_OBJ);
$whenGenerated = $aInfo->whenGenerated;
$sessiontoken = $aInfo->session; //we arent creating a new session here anymore, we take the users current session token and set it in the client
if(($whenGenerated + (300)) > time()) //under the 3 minute interval
{
//remove previous cookies
setcookie("token", null, time(), "/", "alphaland.cc"); //delete non www. cookie
setcookie("token", null, time(), "/", "www.alphaland.cc"); //delete www. cookie
setcookie("token", null, time(), "/", ".alphaland.cc"); //delete (all token?) cookies
// ...
//set new cookie from auth ticket
setcookie("token", $sessiontoken, time() + (86400 * 30), "/", ".alphaland.cc"); //30 day expiration on token for (hopefully) all alphaland paths
// ...
//setcookie("token", $sessiontoken, time() + (86400 * 30), "/", false, true); //30 day expiration on token
}
else
{
die("Auth expired");
}
}
else
{
die("Invalid auth");
}

View File

@ -0,0 +1,238 @@
<?php
/*
This is used on the client (if the client has the session token set) to request a server, join a server and server status messages
TODO: Clean up
*/
$requesttype = $_GET['request'];
$local = $_GET['local'];
$placeid = $_GET['placeid'];
$placeid2 = $_GET['placeId'];
if (!$placeid)
{
$placeid = $placeid2;
}
$userid = $_GET['userid']; //for following
$isTeleport = $_GET['isTeleport'];
function constructJson($jobid, $status, $joinscripturl, $authenticationurl, $authenticationticket, $message)
{
if (empty($message))
{
$message = null;
}
header('Content-Type: application/json');
header("Cache-Control: no-cache, no-store");
header("Pragma: no-cache");
header("Expires: -1");
header("Last-Modified: " . gmdate("D, d M Y H:i:s T") . " GMT");
return json_encode(array(
"jobId" => $jobid,
"status" => $status,
"joinScriptUrl" => $joinscripturl,
"authenticationUrl" => $authenticationurl,
"authenticationTicket" => $authenticationticket,
"message" => $message
), JSON_UNESCAPED_SLASHES);
}
if ($local)
{
die(constructJson("1", 2, "https://alphaland.cc/Game/Join.ashx?ticket=111&local=true", "", "", ""));
}
if(!$requesttype || !$placeid || ($_SERVER['HTTP_USER_AGENT'] != $GLOBALS['clientUserAgent']))
{
die(http_response_code(400));
}
function genToken($jobid) {
$tokencheck = $GLOBALS['pdo']->prepare("SELECT * FROM game_launch_tokens WHERE uid = :u");
$tokencheck->bindParam(":u", $GLOBALS['user']->id, PDO::PARAM_INT);
$tokencheck->execute();
if ($tokencheck->rowCount() > 0)
{
$tokenerase = $GLOBALS['pdo']->prepare("DELETE FROM game_launch_tokens WHERE uid = :u");
$tokenerase->bindParam(":u", $GLOBALS['user']->id, PDO::PARAM_INT);
$tokenerase->execute();
}
$t = genGameLaunchTokenHash(32);
$n = $GLOBALS['pdo']->prepare("INSERT INTO game_launch_tokens(token,uid,jobid,whenCreated) VALUES(:t,:u,:s,UNIX_TIMESTAMP())");
$n->bindParam(":t", $t, PDO::PARAM_INT);
$n->bindParam(":u", $GLOBALS['user']->id, PDO::PARAM_INT);
$n->bindParam(":s", $jobid, PDO::PARAM_INT);
if($n->execute()) {
return $t;
}
}
function StartServer($gid)
{
$gameInfo = getAssetInfo($gid);
$jobuuid = genJobId(); //generate a UUID for the job
$ip = $GLOBALS['gameMachine']; //IP address of the gameserver machine
$port = allocGamePort(); //generate an available port for the gameserver
//add this server to the database
$s = $GLOBALS['pdo']->prepare("INSERT INTO open_servers(jobid,gameID,ip,port,whenStarted,lastPing) VALUES(:j,:g,:ip,:port,UNIX_TIMESTAMP(),UNIX_TIMESTAMP())");
$s->bindParam(":j", $jobuuid, PDO::PARAM_STR);
$s->bindParam(":g", $gid, PDO::PARAM_INT);
$s->bindParam(":ip", $ip, PDO::PARAM_STR);
$s->bindParam(":port", $port, PDO::PARAM_INT);
$s->execute();
//launch the server
$script = file_get_contents($GLOBALS['gameserverscript']);
$gameSpawnResult = soapOpenJobEx($GLOBALS['gamesArbiter'], $jobuuid, 60, "Start Server ".$gid, $script, array(
$gid, //placeid
$port, //gameserver port
"alphaland.cc", //domain
$gameInfo->CreatorId, //place creatorid
(bool)$gameInfo->isPersonalServer //ispersonalserver
)
);
if (is_soap_fault($gameSpawnResult)) {
//log the fault
$theFault = print_r($gameSpawnResult, TRUE);
$description = "Start Gameserver ".$gid." Job";
$fault = $GLOBALS['pdo']->prepare("INSERT INTO soap_faults(jobdescription, script, fault, whenOccurred) VALUES(:jd, :sc, :f, UNIX_TIMESTAMP())");
$fault->bindParam(":jd", $description, PDO::PARAM_STR);
$fault->bindParam(":sc", $script, PDO::PARAM_STR);
$fault->bindParam(":f", $theFault, PDO::PARAM_STR);
$fault->execute();
//something failed, set the server to closed (add a limit if a server fails to start for some reason?)
/*
$s = $GLOBALS['pdo']->prepare("UPDATE open_servers SET status = 2 WHERE jobid = :j AND gameID = :g");
$s->bindParam(":j", $jobuuid, PDO::PARAM_STR);
$s->bindParam(":g", $gid, PDO::PARAM_INT);
$s->execute();
*/
}
return $jobuuid; //return the new job UUID
}
if ($requesttype == "RequestGame") //start new server or join existing one
{
$check = $pdo->prepare("SELECT * FROM assets WHERE id = :i");
$check->bindParam(":i", $placeid, PDO::PARAM_INT);
$check->execute();
if($check->rowCount() > 0)
{
$gInfo = $check->fetch(PDO::FETCH_OBJ);
$assettype = $gInfo->AssetTypeId;
if ($assettype == 9) //asset is game
{
//safe ID
$gameID = $gInfo->id;
checkForDeadJobs($gameID);
if (userAccessToGame($gameID, $user->id))
{
//check for open servers
$servers = $pdo->prepare("SELECT * FROM open_servers WHERE gameID = :i AND (status = 0 OR status = 1) ORDER BY status DESC LIMIT 1");
$servers->bindParam(":i", $gameID, PDO::PARAM_INT);
$servers->execute();
if($servers->rowCount() > 0) //server already available
{
$sInfo = $servers->fetch(PDO::FETCH_OBJ);
if($sInfo->status == 0) //game is opening, send retry signal
{
echo constructJson($sInfo->jobid."", 0, "", "", "", ""); //retry signal
}
elseif($sInfo->status == 1) //game is open, check if its joinable (player count, queue, etc)
{
addPlayerToQueue($gameID, $sInfo->jobid, $user->id); //add player to queue (if they are in it, this updates ping)
if (isNextInQueue($gameID, $sInfo->jobid, $user->id)) //player next in queue
{
if (jobPlayerCount($gameID, $sInfo->jobid) >= $gInfo->MaxPlayers)
{
echo constructJson($sInfo->jobid."", 6, "", "", "", ""); //return job full
}
else
{
$newticket = genToken($sInfo->jobid);
echo constructJson($sInfo->jobid."", 2, "https://alphaland.cc/Game/Join.ashx?ticket=" .$newticket, "", "", "");
}
}
else
{
echo constructJson($sInfo->jobid."", 6, "", "", "", ""); //return job full
}
}
}
else //no available servers
{
$sQ = $pdo->prepare("SELECT * FROM open_servers WHERE (status = 0 OR status = 1) AND gameID = :i");
$sQ->bindParam(":i", $gameID, PDO::PARAM_INT);
$sQ->execute();
if($sQ->rowCount() == 0) //check one more time if a server spawned
{
$newjob = StartServer($gameID);
echo constructJson($newjob."", 0, "", "", "", ""); //retry signal
}
}
}
}
}
}
else if ($requesttype == "RequestFollowUser") //follow user
{
if ($userid)
{
$check = $pdo->prepare("SELECT * FROM assets WHERE id = :i");
$check->bindParam(":i", $placeid, PDO::PARAM_INT);
$check->execute();
if($check->rowCount() > 0) //asset exists
{
$gInfo = $check->fetch(PDO::FETCH_OBJ);
$assettype = $gInfo->AssetTypeId;
if ($assettype == 9) //asset is a game
{
checkForDeadJobs($placeid);
$playersgame = $pdo->prepare("SELECT * FROM game_presence WHERE uid = :u AND placeid = :p");
$playersgame->bindParam(":u", $userid, PDO::PARAM_INT);
$playersgame->bindParam(":p", $placeid, PDO::PARAM_INT);
$playersgame->execute();
if ($playersgame->rowCount() > 0) //player is in a job, check if full
{
$playersgamejobid = $playersgame->fetch(PDO::FETCH_OBJ)->jobid;
$mcheck = $pdo->prepare("SELECT COUNT(*) FROM game_presence WHERE jobid = :j AND (lastPing + 50) > UNIX_TIMESTAMP()");
$mcheck->bindParam(":j", $playersgamejobid, PDO::PARAM_STR);
$mcheck->execute();
if($mcheck->fetchColumn(0) >= $gInfo->MaxPlayers) //players job is full
{
echo constructJson($mcheck->fetch(PDO::FETCH_OBJ)->jobid."", 6, "", "", "", ""); //return job full
}
else //job isnt full, join it
{
$newticket = genToken($playersgamejobid);
echo constructJson($playersgamejobid."", 2, "https://alphaland.cc/Game/Join.ashx?ticket=" .$newticket, "", "", "");
}
}
else //user left game
{
echo constructJson("", 10, "", "", "", ""); //user left job signal
}
}
}
}
}

View File

@ -0,0 +1,15 @@
<?php
RCCHeaderEnvironment();
$jobid = (string)$_GET['jobId'];
$q = $pdo->prepare("SELECT * FROM open_servers WHERE jobid = :j AND status = 0");
$q->bindParam(":j", $jobid, PDO::PARAM_STR);
$q->execute();
if($q->rowCount() > 0) {
$u = $pdo->prepare("UPDATE open_servers SET status = 1 WHERE jobid = :j");
$u->bindParam(":j", $jobid, PDO::PARAM_STR);
$u->execute();
}
die();

40
html/Game/ServerPing.php Normal file
View File

@ -0,0 +1,40 @@
<?php
RCCHeaderEnvironment();
$placeid = (int)$_GET['PlaceID'];
$jobid = (string)$_GET['JobID'];
if (!$jobid || !$placeid)
{
http_response_code(400);
}
else
{
$server = $pdo->prepare("SELECT * FROM open_servers WHERE gameID = :g AND jobid = :j");
$server->bindParam(":g", $placeid, PDO::PARAM_INT);
$server->bindParam(":j", $jobid, PDO::PARAM_STR);
$server->execute();
if ($server->rowCount() > 0) //job exists with the parameters
{
$players = $pdo->prepare("SELECT * FROM game_presence WHERE placeid = :p AND jobid = :j AND (lastPing + 50) > UNIX_TIMESTAMP()");
$players->bindParam(":p", $placeid, PDO::PARAM_INT);
$players->bindParam(":j", $jobid, PDO::PARAM_STR);
$players->execute();
if ($players->rowCount() > 0) //atleast 1 player in job
{
soapRenewLease($GLOBALS['gamesArbiter'], $jobid, 90); //add 1.50 min to the job
}
$newping = $pdo->prepare("UPDATE open_servers SET lastPing = UNIX_TIMESTAMP() WHERE gameID = :g AND jobid = :j");
$newping->bindParam(":g", $placeid, PDO::PARAM_INT);
$newping->bindParam(":j", $jobid, PDO::PARAM_STR);
$newping->execute();
}
else
{
http_response_code(400);
}
}

View File

@ -0,0 +1,75 @@
<?php
$fmt = $_GET['fmt'];
$wd = $_GET['wd'];
$ht = $_GET['ht'];
$aid = $_GET['aid'];
//grab the requested asset information
$check = $pdo->prepare("SELECT * FROM assets WHERE id = :i");
$check->bindParam(":i", $aid, PDO::PARAM_INT);
$check->execute();
// ...
//grab the default asset image
$defaultassetimage = 126; //default asset image is asset id 126
$defaultid = $pdo->prepare("SELECT * FROM assets WHERE id = :i");
$defaultid->bindParam(":i", $defaultassetimage, PDO::PARAM_INT);
$defaultid->execute();
$defaultid = $defaultid->fetch(PDO::FETCH_OBJ);
$defaultidhash = $defaultid->Hash;
// ...
//grab the moderated asset image
$moderatedassetimage = 193;
$moderatedid = $pdo->prepare("SELECT * FROM assets WHERE id = :i");
$moderatedid->bindParam(":i", $moderatedassetimage, PDO::PARAM_INT);
$moderatedid->execute();
$moderatedid = $moderatedid->fetch(PDO::FETCH_OBJ);
$moderatedhash = $moderatedid->Hash;
// ...
//grab the pending asset image
$pendingassetimage = 194;
$pendingid = $pdo->prepare("SELECT * FROM assets WHERE id = :i");
$pendingid->bindParam(":i", $pendingassetimage, PDO::PARAM_INT);
$pendingid->execute();
$pendingid = $pendingid->fetch(PDO::FETCH_OBJ);
$pendinghash = $pendingid->Hash;
// ...
if ($check->rowCount() > 0) //asset exists on Alphaland
{
$check = $check->fetch(PDO::FETCH_OBJ);
if ($check->IsModerated == false && $check->IsApproved == true)
{
//assuming its none of these asset types, redirect to ROBLOX
if ($check->AssetTypeId == 4) //handle mesh asset, return default image for now (TODO: RENDER THESE)
{
redirect("https://tcdn.alphaland.cc/" . $defaultidhash);
}
elseif ($check->AssetTypeId == 40) //handle MeshPart asset, return default image for now (TODO: RENDER THESE)
{
redirect("https://tcdn.alphaland.cc/" . $defaultidhash);
}
elseif ($check->AssetTypeId == 10) //handle model asset, return default image for now (TODO: RENDER THESE)
{
if (!empty($check->ThumbHash)) //if a render was ever performed
{
$thumbhash = $check->ThumbHash;
redirect("https://trcdn.alphaland.cc/" . $thumbhash);
}
redirect("https://tcdn.alphaland.cc/" . $defaultidhash);
}
elseif ($check->AssetTypeId == 39) //handle SolidModel asset, return default image for now (TODO: RENDER THESE)
{
redirect("https://tcdn.alphaland.cc/" . $defaultidhash);
}
}
}
else
{
redirect('https://www.roblox.com/Game/Tools/ThumbnailAsset.ashx?fmt=' . $fmt . '&wd=' . $wd . '&ht=' . $ht . '&aid=' . $aid);
}

165
html/Game/Visit.ashx Normal file
View File

@ -0,0 +1,165 @@
<?php
?>
--rbxsig%odhcxu5vGMNOxN3ABSOu00opgsWeMDrsPejo2ZJDt0PPQgecAZifXKTdzIFG7tCVzABfO5Uggm1zLyiNKPC2QO31jmgKEBAWvU11RE6zvMOwG45rV2nGszwp52DGFyvNfIzcl0dfYPJot/WzRKdOXTCp8r16AGzkEe9g1gtq6i4=%
-- Prepended to Edit.lua and Visit.lua and Studio.lua and PlaySolo.lua--
function ifSeleniumThenSetCookie(key, value)
if false then
game:GetService("CookiesService"):SetCookieValue(key, value)
end
end
ifSeleniumThenSetCookie("SeleniumTest1", "Inside the visit lua script")
pcall(function() game:SetPlaceID(0) end)
pcall(function() game:SetUniverseId(0) end)
visit = game:GetService("Visit")
local message = Instance.new("Message")
message.Parent = workspace
message.archivable = false
game:GetService("ScriptInformationProvider"):SetAssetUrl("http://assetgame.roblox.com/Asset/")
game:GetService("ContentProvider"):SetThreadPool(16)
pcall(function() game:GetService("InsertService"):SetFreeModelUrl("http://assetgame.roblox.com/Game/Tools/InsertAsset.ashx?type=fm&q=%s&pg=%d&rs=%d") end) -- Used for free model search (insert tool)
pcall(function() game:GetService("InsertService"):SetFreeDecalUrl("http://assetgame.roblox.com/Game/Tools/InsertAsset.ashx?type=fd&q=%s&pg=%d&rs=%d") end) -- Used for free decal search (insert tool)
ifSeleniumThenSetCookie("SeleniumTest2", "Set URL service")
settings().Diagnostics:LegacyScriptMode()
game:GetService("InsertService"):SetBaseSetsUrl("http://assetgame.roblox.com/Game/Tools/InsertAsset.ashx?nsets=10&type=base")
game:GetService("InsertService"):SetUserSetsUrl("http://assetgame.roblox.com/Game/Tools/InsertAsset.ashx?nsets=20&type=user&userid=%d")
game:GetService("InsertService"):SetCollectionUrl("http://assetgame.roblox.com/Game/Tools/InsertAsset.ashx?sid=%d")
game:GetService("InsertService"):SetAssetUrl("http://assetgame.roblox.com/Asset/?id=%d")
game:GetService("InsertService"):SetAssetVersionUrl("http://assetgame.roblox.com/Asset/?assetversionid=%d")
pcall(function() game:GetService("SocialService"):SetFriendUrl("http://assetgame.roblox.com/Game/LuaWebService/HandleSocialRequest.ashx?method=IsFriendsWith&playerid=%d&userid=%d") end)
pcall(function() game:GetService("SocialService"):SetBestFriendUrl("http://assetgame.roblox.com/Game/LuaWebService/HandleSocialRequest.ashx?method=IsBestFriendsWith&playerid=%d&userid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupUrl("http://assetgame.roblox.com/Game/LuaWebService/HandleSocialRequest.ashx?method=IsInGroup&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupRankUrl("http://assetgame.roblox.com/Game/LuaWebService/HandleSocialRequest.ashx?method=GetGroupRank&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupRoleUrl("http://assetgame.roblox.com/Game/LuaWebService/HandleSocialRequest.ashx?method=GetGroupRole&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("GamePassService"):SetPlayerHasPassUrl("http://assetgame.roblox.com/Game/GamePass/GamePassHandler.ashx?Action=HasPass&UserID=%d&PassID=%d") end)
pcall(function() game:GetService("MarketplaceService"):SetProductInfoUrl("https://api.roblox.com/marketplace/productinfo?assetId=%d") end)
pcall(function() game:GetService("MarketplaceService"):SetDevProductInfoUrl("https://api.roblox.com/marketplace/productDetails?productId=%d") end)
pcall(function() game:GetService("MarketplaceService"):SetPlayerOwnsAssetUrl("https://api.roblox.com/ownership/hasasset?userId=%d&assetId=%d") end)
pcall(function() game:SetCreatorID(0, Enum.CreatorType.User) end)
ifSeleniumThenSetCookie("SeleniumTest3", "Set creator ID")
pcall(function() game:SetScreenshotInfo("") end)
pcall(function() game:SetVideoInfo("") end)
function registerPlay(key)
if true and game:GetService("CookiesService"):GetCookieValue(key) == "" then
game:GetService("CookiesService"):SetCookieValue(key, "{ \"userId\" : 0, \"placeId\" : 0, \"os\" : \"" .. settings().Diagnostics.OsPlatform .. "\"}")
end
end
pcall(function()
registerPlay("rbx_evt_ftp")
delay(60*5, function() registerPlay("rbx_evt_fmp") end)
end)
ifSeleniumThenSetCookie("SeleniumTest4", "Exiting SingleplayerSharedScript")-- SingleplayerSharedScript.lua inserted here --
pcall(function() settings().Rendering.EnableFRM = true end)
pcall(function() settings()["Task Scheduler"].PriorityMethod = Enum.PriorityMethod.AccumulatedError end)
game:GetService("ChangeHistoryService"):SetEnabled(false)
pcall(function() game:GetService("Players"):SetBuildUserPermissionsUrl("http://assetgame.roblox.com//Game/BuildActionPermissionCheck.ashx?assetId=0&userId=%d&isSolo=true") end)
workspace:SetPhysicsThrottleEnabled(true)
local addedBuildTools = false
local screenGui = game:GetService("CoreGui"):FindFirstChild("RobloxGui")
local inStudio = false or false
function doVisit()
message.Text = "Loading Game"
if false then
if false then
success, err = pcall(function() game:Load("") end)
if not success then
message.Text = "Could not teleport"
return
end
end
else
if false then
game:Load("")
pcall(function() visit:SetUploadUrl("") end)
else
pcall(function() visit:SetUploadUrl("") end)
end
end
message.Text = "Running"
game:GetService("RunService"):Run()
message.Text = "Creating Player"
if false or false then
player = game:GetService("Players"):CreateLocalPlayer(0)
if not inStudio then
player.Name = [====[Guest 6055]====]
end
else
player = game:GetService("Players"):CreateLocalPlayer(0)
end
player.CharacterAppearance = "http://assetgame.roblox.com/Asset/CharacterFetch.ashx?userId=1&placeId=0"
local propExists, canAutoLoadChar = false
propExists = pcall(function() canAutoLoadChar = game.Players.CharacterAutoLoads end)
if (propExists and canAutoLoadChar) or (not propExists) then
player:LoadCharacter()
end
message.Text = "Setting GUI"
player:SetSuperSafeChat(true)
pcall(function() player:SetUnder13(True) end)
pcall(function() player:SetMembershipType(None) end)
pcall(function() player:SetAccountAge(0) end)
if not inStudio and false then
message.Text = "Setting Ping"
visit:SetPing("http://assetgame.roblox.com/Game/ClientPresence.ashx?version=old&PlaceID=0", 120)
message.Text = "Sending Stats"
game:HttpGet("")
end
end
success, err = pcall(doVisit)
if not inStudio and not addedBuildTools then
local playerName = Instance.new("StringValue")
playerName.Name = "PlayerName"
playerName.Value = player.Name
playerName.RobloxLocked = true
playerName.Parent = screenGui
pcall(function() game:GetService("ScriptContext"):AddCoreScript(59431535,screenGui,"BuildToolsScript") end)
addedBuildTools = true
end
if success then
message.Parent = nil
else
print(err)
if not inStudio then
if false then
pcall(function() visit:SetUploadUrl("") end)
end
end
wait(5)
message.Text = "Error on visit: " .. err
if not inStudio then
if false then
game:HttpPost("https://data.roblox.com/Error/Lua.ashx", "Visit.lua: " .. err)
end
end
end

4
html/Game/authticket.php Normal file
View File

@ -0,0 +1,4 @@
<?php
//echo $_COOKIE['token'];
echo genTicket();

37
html/MCP/approveasset.php Normal file
View File

@ -0,0 +1,37 @@
<?php
/*
Alphaland 2021
*/
//headers
header("Access-Control-Allow-Origin: https://www.alphaland.cc");
header("access-control-allow-credentials: true");
if(!$user->isStaff())
{
redirect("../home"); //u not admin nigga
}
$assetid = $_GET['id'];
if (!$assetid)
{
http_response_code(400);
}
else
{
if (isThumbnailerAlive()) {
$approve = approveAsset($assetid);
if ($approve === true) {
logStaffAction("Approved Asset ".$assetid);
$approve = "Approved Asset";
}
} else {
$approve = "Thumbnailer Offline";
}
header('Content-Type: application/json');
echo json_encode(array("alert" => $approve));
}

View File

@ -0,0 +1,105 @@
<?php
if(!$user->isStaff())
{
redirect("../home"); //u not admin nigga
}
$body = <<<EOT
<h5 class="text-center">Asset Approvals</h5>
<h5 class="text-center">If you deny an asset, it will Moderate it and delete all associated files. Be sure of your decision</h5>
<h5 class="text-center">Report any issues in the staff chat in the Discord server</h5>
<div class="container">
<div id = "error_alert" class="alert alert-danger" role="alert" style="display:none;"></div>
<div class = "card">
<div class="row">
<div class="container pb-3">
<div id = "assets-container" class="card-body text-center">
</div>
<div class="container mt-2 mb-2 text-center">
<div id="page-buttons" class="btn-group" role="group" aria-label="First group">
</div>
</div>
</div>
</div>
</div>
</div>
<script>
var currentPage = 1;
function moderateAsset(id)
{
getJSONCDS("https://www.alphaland.cc/MCP/moderateasset?id="+id)
.done(function(object)
{
var alert = object.alert;
var messageid = "#error_alert";
if (alert == "Moderated Asset") {
assetPage(currentPage);
}
else
{
$(messageid).text(alert);
$(messageid).show();
window.scrollTo({top: 0, behavior: "smooth"});
setTimeout(function()
{
$(messageid).hide();
}, 3000);
}
});
}
function approveAsset(id)
{
getJSONCDS("https://www.alphaland.cc/MCP/approveasset?id="+id)
.done(function(object)
{
var alert = object.alert;
var messageid = "#error_alert";
if (alert == "Approved Asset") {
assetPage(currentPage);
}
else
{
$(messageid).text(alert);
$(messageid).show();
window.scrollTo({top: 0, behavior: "smooth"});
setTimeout(function()
{
$(messageid).hide();
}, 3000);
}
});
}
function assetPage(num, keyword = "")
{
currentPage = num;
var html= '<div class="mod-ul-container">';
html +='<ul>';
html +='<li>';
html +='<div class="card">';
html +='<a href="/catalog/view?id={assetid}">';
html +='<div class="card-body">';
html +='<img class="img-fluid" src="{image}" style="min-width:128px;max-width:128px;min-height:128px;max-height:128px;">';
html +='<a style="color:grey;text-decoration:none;" class="no-overflow mb-1">{name}</a>';
html +='<button onclick="approveAsset({assetid})" class="btn btn-sm btn-success w-100">Approve</button>';
html +='<div class="w-100 mb-1"></div>';
html +='<button onclick="moderateAsset({assetid})" class="btn btn-sm btn-danger w-100">Deny</button>';
html +='</div>';
html +='</a>';
html +='</div>';
html +='</li>';
html +='</ul>';
html +='</div>';
multiPageHelper("assetPage", "https://www.alphaland.cc/MCP/pendingassets", "https://api.alphaland.cc/logo", "#assets-container", "#page-buttons", html, num, 10, "", "No pending assets");
}
assetPage(currentPage);
</script>
EOT;
pageHandler();
$ph->pageTitle("Asset Approvals");
$ph->body = $body;
$ph->output();

View File

@ -0,0 +1,104 @@
<?php
$body = <<<EOT
<h5 class="text-center">Chat Logs</h5>
<h5 class="text-center">You can sort by Censored, by username and search for words</h5>
<h5 class="text-center">If you believe a user deserves a ban, start off with a warning</h5>
<hr>
<div class="container-fluid">
<div class="container">
<div class="col-sm marg-bot-15">
<div class="card marg-auto" style="min-height:16rem;">
<div class="card-body">
<h5>Chat Logs</h5>
<div class="row">
<div class="col-sm">
<div class="input-group">
<div class="input-group">
<input type="text" id="username_query" class="form-control" autocomplete="off" placeholder="Username">
<div class="input-group-append">
<button type="button" onclick="setUsername($('#username_query').val())" class="btn btn-success" type="button">Sort</button>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm">
<div class="input-group">
<div class="input-group">
<input type="text" id="search_query" class="form-control" autocomplete="off" placeholder="Search">
<div class="input-group-append">
<button type="button" onclick="setSearchQuery($('#search_query').val())" class="btn btn-success" type="button">Search</button>
</div>
</div>
</div>
</div>
</div>
<hr>
<div id="message-container">
</div>
<div class="container mt-2 mb-2 text-center">
<div id="page-buttons" class="btn-group" role="group" aria-label="First group">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
/*
Alphaland 2021
*/
var usernamequery = "";
var searchquery = "";
function setSearchQuery(query)
{
searchquery = query;
logsPage(1);
}
function setUsername(username)
{
usernamequery = username;
logsPage(1);
}
function logsPage(num)
{
var html = '<div class="row">';
html+= '<div class="col-sm marg-bot-15">';
html+= '<div class="card">';
html+= '<div class="card-body">';
html+= '<h6>From <a class="red-a" href="/profile/view?id={userid}"> {username}</a> : <a style="color:grey;"> {date}</a></h6>';
html+= '<h6>Game:<a class="red-a" href="/games/view?id={placeId}"> {placeName}</a></h6>';
html+= '<div class="row marg-bot-15">';
html+= '<div class="col-sm-2">';
html+= '<a href="/profile/view?id={userid}"><img class="card-img-top marg-bot-15" src="{thumbnail}" style="width:4rem;border-radius:100%;"></a>';
html+= '</div>';
html+= '<div class="col-sm" style="overflow:hidden;">';
html+= '<p>"{message}"</p>';
html+= '</div>';
html+= '</div>';
html+= '</div>';
html+= '</div>';
html+= '</div>';
html+= '</div>';
multiPageHelper("logsPage", "https://www.alphaland.cc/MCP/chat-logs/loggedChats", "https://api.alphaland.cc/logo", "#message-container", "#page-buttons", html, num, 40, searchquery, "No Results", "&username="+usernamequery);
}
logsPage(1);
</script>
EOT;
pageHandler();
$ph->pageTitle("Chat Logs");
$ph->body = $body;
$ph->output();

View File

@ -0,0 +1,88 @@
<?php
/*
Alphaland 2021
*/
//headers
header("Access-Control-Allow-Origin: https://www.alphaland.cc");
header("access-control-allow-credentials: true");
header('Content-Type: application/json');
//get params
$username = $_GET['username'];
$userid = getID($username);
$infractions = (bool)$_GET['infractions'];
$page = $_GET['page'];
$limit = $_GET['limit'];
$keyword = substr((string)$_GET['keyword'], 0, 32); //32 limit
$keywordq = '%'.$keyword.'%'; //query
//initial checks
if (!$limit || !$page)
{
http_response_code(400);
}
if ($page < 1 || $limit < 1)
{
http_response_code(400);
}
//$query = "SELECT * FROM chat_logs WHERE whoSent = :who AND trippedFilter = :tf";
$query = "SELECT * FROM chat_logs WHERE message LIKE :u" . (!empty($userid) && is_int($userid)?" AND whoSent = ".$userid." ":" ") . " AND whoSent > 2 ORDER BY whenSent DESC";
//count how many games without offset/limit
$messagescount = $pdo->prepare($query);
$messagescount->bindParam(':u', $keywordq, PDO::PARAM_STR);
$messagescount->execute();
$messagescount = $messagescount->rowCount();
//data for pages
$total = $messagescount;
$pages = ceil($total / $limit);
$offset = ($page - 1) * $limit;
// Prepare the paged query (if keyword isnt empty, it will be used)
$messages = $pdo->prepare($query . ' LIMIT :limit OFFSET :offset');
$messages->bindParam(':u', $keywordq, PDO::PARAM_STR);
$messages->bindParam(':limit', $limit, PDO::PARAM_INT);
$messages->bindParam(':offset', $offset, PDO::PARAM_INT);
$messages->execute();
//final check to see if page is invalid
if ($pages > 0)
{
if ($page > $pages)
{
http_response_code(400);
}
}
//construct the json array
$jsonData = array(
"pageCount" => $pages,
"pageResults" => (int)$messages->rowCount()
);
foreach($messages as $message)
{
$userid = $message['whoSent'];
$gameAssetId = $message['gameAssetId'];
$loggedMessage = $message['message'];
$whenlogged = date("m/d/Y", $message['whenSent']);
$loggedMessages = array(
"userid" => $userid,
"username" => getUsername($userid),
"thumbnail" => getPlayerRender($userid),
"placeName" => getAssetInfo($gameAssetId)->Name,
"placeId" => $gameAssetId,
"message" => $loggedMessage,
"date" => $whenlogged
);
array_push($jsonData, $loggedMessages);
}
// ...
die(json_encode($jsonData));

49
html/MCP/index.php Normal file
View File

@ -0,0 +1,49 @@
<?php
if(!($user->isStaff()))
{
redirect("../404"); //u not admin nigga
}
$body = <<<EOT
<h5 class="text-center">Moderation Control Panel</h5>
<div class="container text-center">
<div class="row">
<div class="col-sm">
<div class="card marg-bot-30">
<div class="card-body text-center">
<a class="red-a-nounder" href="user-management"><p style="font-size:10rem;"><i class="fas fa-user-shield"></i></p></a>
<a class="red-a-nounder" href="user-management"><h5>User Management</h5></a>
</div>
</div>
</div>
<div class="col-sm">
<div class="card marg-bot-30">
<div class="card-body">
<a class="blue-a-nounder" href="asset-management"><p style="font-size:10rem;"><i class="fab fa-redhat"></i></p></a>
<a class="blue-a-nounder" href="asset-management"><h5>Asset Approval</h5></a>
</div>
</div>
</div>
<div class="col-sm">
<div class="card marg-bot-30">
<div class="card-body text-center">
<a class="green-a-nounder" href="chat-logs"><p style="color:#3ffa42;font-size:10rem;"><i class="fas fa-hammer"></i></p></a>
<a class="green-a-nounder" href="chat-logs"><h5>Chat Logs</h5></a>
</div>
</div>
</div>
<div class="col-sm">
<div class="card marg-bot-30">
<div class="card-body text-center">
<a class="red-a-nounder" href="invite-logs"><p style="font-size:10rem;"><i class="fas fa-user-shield"></i></p></a>
<a class="red-a-nounder" href="invite-logs"><h5>Invite Logs</h5></a>
</div>
</div>
</div>
</div>
</div>
EOT;
pageHandler();
$ph->pageTitle("Moderation");
$ph->body = $body;
$ph->output();
?>

View File

@ -0,0 +1,55 @@
<?php
if(!($user->isStaff()))
{
die();
}
$alert = '';
$body = <<<EOT
<div class="container">
<div class="row">
<div class="col-sm">
<div class="card">
<div class="card-body">
<h4>User Invitation Logs</h4>
<div class="card-body">
<table class="table atable-dark">
<thead>
<tr>
<th>Invited</th>
<th>whoInvited</th>
<th>whenAccepted</th>
</tr>
</thead>
<tbody id="invite_logs">
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function activeKeys()
{
var html = '<tr>';
html += '<td>{invitedUsername} ({invitedUser})</td>';
html += '<td>{whoInvitedUsername} ({whoInvited})</td>';
html += '<td>{whenAccepted}</td>';
html += '</tr>';
staticPageHelper("https://www.alphaland.cc/MCP/invite-logs/inviteLogs", "", "#invite_logs", html, "", 999999999999, "", "");
}
activeKeys();
</script>
EOT;
pageHandler();
$ph->pageTitle("Invite Logs");
$ph->body = $body;
$ph->output();

View File

@ -0,0 +1,39 @@
<?php
if(!($user->isStaff())) {
die();
}
//headers
header("Access-Control-Allow-Origin: https://www.alphaland.cc");
header("access-control-allow-credentials: true");
header("Cache-Control: no-cache");
header("Pragma: no-cache");
header("Expires: -1");
header("Last-Modified: " . gmdate("D, d M Y H:i:s T") . " GMT");
header('Content-Type: application/json');
$b = $pdo->prepare("SELECT * FROM `users_invited` ORDER BY whenAccepted DESC");
$b->execute();
$jsonData = array();
foreach($b as $inviteInfo)
{
$invitedUser = $inviteInfo['invitedUser'];
$whoInvited = $inviteInfo['whoInvited'];
$whenAccepted = $inviteInfo['whenAccepted'];
$jsonInfo = array(
"invitedUser" => $invitedUser,
"invitedUsername" => cleanOutput(getUsername($invitedUser)),
"whoInvited" => $whoInvited,
"whoInvitedUsername" => cleanOutput(getUsername($whoInvited)),
"whenAccepted" => date("m/d/Y", $whenAccepted)
);
array_push($jsonData, $jsonInfo);
}
// ...
die(json_encode($jsonData));

View File

@ -0,0 +1,33 @@
<?php
/*
Alphaland 2021
*/
//headers
header("Access-Control-Allow-Origin: https://www.alphaland.cc");
header("access-control-allow-credentials: true");
if(!$user->isStaff())
{
redirect("../home"); //u not admin nigga
}
$assetid = $_GET['id'];
if (!$assetid)
{
http_response_code(400);
}
else
{
$moderate = moderateAsset($assetid);
if ($moderate === true) {
logStaffAction("Moderated Asset ".$assetid);
$moderate = "Moderated Asset";
}
header('Content-Type: application/json');
echo json_encode(array("alert" => $moderate));
}

View File

@ -0,0 +1,88 @@
<?php
/*
Alphaland 2021
*/
if(!$user->isStaff())
{
redirect("../home"); //u not admin nigga
}
//headers
header("Access-Control-Allow-Origin: https://www.alphaland.cc");
header("access-control-allow-credentials: true");
header('Content-Type: application/json');
//get params
$page = $_GET['page'];
$limit = $_GET['limit'];
//initial checks
if (!$limit || !$page)
{
http_response_code(400);
}
if ($page < 1 || $limit < 1)
{
http_response_code(400);
}
$assetscount = fetchPendingAssets()->rowCount();
//data for pages
$total = $assetscount;
$pages = ceil($total / $limit);
$offset = ($page - 1) * $limit;
// Prepare the paged query (if keyword isnt empty, it will be used)
$assets = fetchPendingAssets('LIMIT '.$limit.' OFFSET '.$offset);
//final check to see if page is invalid
if ($pages > 0)
{
if ($page > $pages)
{
http_response_code(400);
}
}
//construct the json array
$jsonData = array(
"pageCount" => $pages,
"pageResults" => (int)$assets->rowCount()
);
foreach($assets as $asset)
{
$assetid = $asset['id'];
$creatorid = $asset['CreatorId'];
$assettypeid = $asset['AssetTypeId'];
$name = cleanOutput($asset['Name']);
$desc = cleanOutput($asset['Description']); //description of the game
$creatorname = getUsername($creatorid); //creator of the game username
$image = "";
if ($assettypeid == 2|| $assettypeid == 11 || $assettypeid == 12) { //tshirts, shirts and pants
$image = getSPTCosmeticTexture($assetid);
} else {
$image = getImageFromAsset($assetid); //anything else probably
}
$assetInfo = array(
"assetid" => $assetid,
"assettypeid" => $assettypeid,
"name" => $name,
"description" => $desc,
"creatorname" => $creatorname,
"creatorid" => $creatorid,
"image" => $image
);
array_push($jsonData, $assetInfo);
}
// ...
die(json_encode($jsonData));

View File

@ -0,0 +1,198 @@
<?php
$body = '';
if(!($user->isStaff()))
{
redirect("../404"); //u not admin nigga
}
$alert = "";
if(isset($_POST['unbanuser']))
{
$id = getID($_POST['unbanuser']);
if (unbanUser($id))
{
logStaffAction("Unbanned User ".$id);
$alert = "<div class='alert alert-success' role='alert'>Unbanned {$_POST['unbanuser']}</div>";
}
else
{
$alert = "<div class='alert alert-danger' role='alert'>Failed to unban user</div>";
}
}
if(isset($_POST['banuser']))
{
$postcount = count($_POST);
if ($postcount > 3)
{
$alert = "<div class='alert alert-danger' role='alert'>An error occurred</div>";
}
elseif (empty($_POST['banuser']))
{
$alert = "<div class='alert alert-danger' role='alert'>No username provided</div>";
}
elseif(usernameExists($_POST['banuser']) == false)
{
$alert = "<div class='alert alert-danger' role='alert'>No account with that username found</div>";
}
elseif (empty($_POST['banreason']))
{
$alert = "<div class='alert alert-danger' role='alert'>No ban reason provided</div>";
}
elseif ($postcount < 3)
{
$alert = "<div class='alert alert-danger' role='alert'>Please select a ban type</div>";
}
else
{
$bantype = 0; //default warning bantype
$banexpiration = 0;
if (isset($_POST['temp_checkbox']))
{
//tempban
$bantype = 1;
$banexpiration = time() + 86400; //add one day to current time
}
elseif (isset($_POST['perm_checkbox']))
{
//perm ban
$bantype = 2;
}
$id = getID($_POST['banuser']);
if (banUser($id, cleanInput($_POST['banreason']), $banexpiration, $bantype))
{
logStaffAction("Banned User ".$id);
$alert = "<div class='alert alert-success' role='alert'>Banned {$_POST['banuser']}</div>";
}
else
{
$alert = "<div class='alert alert-danger' role='alert'>Failed to ban user</div>";
}
}
}
$b = $pdo->prepare("SELECT * FROM user_bans WHERE valid = 1");
$b->bindParam(":i", $id, PDO::PARAM_INT);
$b->execute();
$banneduser = "";
if ($b->rowCount() > 0)
{
foreach ($b as $bannedplayer)
{
$banneddate = date("m/d/Y", $bannedplayer['whenBanned']);
$bannedusername = getUsername($bannedplayer['uid']);
$bannedreason = cleanOutput($bannedplayer['banReason']);
$bannedExpiration = (int)$bannedplayer['banExpiration'];
$bannedType = (int)$bannedplayer['banType'];
if ($bannedType == 0)
{
$bannedExpiration = "Warning";
}
elseif ($bannedType == 2)
{
$bannedExpiration = "Permanent";
}
else
{
$bannedExpiration = date("m/d/Y", $bannedplayer['banExpiration']);
}
$banneduser .= <<<EOT
<tr>
<td>{$banneddate}</td>
<td>{$bannedusername}</td>
<td>{$bannedreason}</td>
<td>{$bannedExpiration}</td>
</tr>
EOT;
}
}
$body = <<<EOT
<div class="container text-center">
{$alert}
<h5>User Management</h5>
<div class="card" style="max-width: 38rem;margin: auto;">
<div class="card-body">
<form method="post">
<div class="row">
<div class="col-sm">
<div class="input-group">
<input type="text" name="banuser" class="form-control" placeholder="Username">
<input type="text" name="banreason" class="form-control" placeholder="Ban Reason">
<div class="input-group-append">
<button type="submit" class="btn btn-danger" type="button">Ban</button>
</div>
</div>
</div>
</div>
<br>
<div class="custom-control custom-checkbox custom-control-inline">
<input type="checkbox" name="warning_checkbox" class="custom-control-input sev_check" id="warning">
<label class="custom-control-label" for="warning">Warning</label>
</div>
<div class="custom-control custom-checkbox custom-control-inline">
<input type="checkbox" name="temp_checkbox" class="custom-control-input sev_check" id="temp">
<label class="custom-control-label" for="temp">Temporary (1 day)</label>
</div>
<div class="custom-control custom-checkbox custom-control-inline">
<input type="checkbox" name="perm_checkbox" class="custom-control-input sev_check" id="perm">
<label class="custom-control-label" for="perm">Permanent</label>
</div>
<script type="text/javascript">
$('.sev_check').click(function() {
$('.sev_check').not(this).prop('checked', false);
});
</script>
</form>
<hr>
<form method="post">
<div class="row">
<div class="col-sm">
<div class="input-group">
<form action="" method="post">
<input type="text" name="unbanuser" class="form-control" placeholder="Username">
<div class="input-group-append">
<button type="submit" class="btn btn-success" type="button">Unban</button>
</div>
</form>
</div>
</div>
</div>
</form>
<hr>
<div class="text-center">
<p>
<button class="btn btn-danger w-100" type="button" data-toggle="collapse" data-target="#banlisttemp" aria-expanded="false" aria-controls="banlisttemp">Banlist</button>
</p>
<div class="collapse" id="banlisttemp">
<table class="table atable-dark">
<thead>
<tr>
<th>Date</th>
<th>Username</th>
<th>Reason</th>
<th>Expiration</th>
</tr>
</thead>
<tbody>
{$banneduser}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
EOT;
pageHandler();
$ph->pageTitle("User Manage");
$ph->body = $body;
$ph->output();
?>

View File

@ -0,0 +1,109 @@
<?php
/*
Alphaland 2021
This is for uploading data from studio, this requires the user to have access to the asset.
*/
$id = (int)$_GET['id'];
$iteminfo = getAssetInfo($id);
if($iteminfo !== FALSE) //asset id exists in alphaland db
{
if ($iteminfo->AssetTypeId == 9) //place
{
$content = gzdecode(file_get_contents('php://input'));
//TODO: implement a .RBXL parser
if (strpos($content, "Workspace") !==false and strpos($content, "PhysicsService") !==false and strpos($content, "SoundService") !==false and strpos($content, "Lighting") !==false)
{
if (isAssetApproved($id) and !isAssetModerated($id)) //if the asset is approved and not moderated
{
if ($iteminfo->CreatorId == $user->id)
{
//generate new hash for the asset
$assethash = genAssetHash(16);
// ...
//upload directory
$uploadDirectory = $GLOBALS['assetCDNPath']; //directory where the assets are stored
// ...
//lock asset db
$pdo->exec("LOCK TABLES assets WRITE"); //lock since this stuff is sensitive
// ...
//delete old hash
unlink($uploadDirectory . $iteminfo->Hash);
// ...
//change asset to use new hash
$s = $pdo->prepare("UPDATE assets SET Hash = :hash WHERE id = :id");
$s->bindParam(":hash", $assethash, PDO::PARAM_STR);
$s->bindParam(":id", $iteminfo->id, PDO::PARAM_INT);
$s->execute();
// ...
//add new asset
$success = file_put_contents($uploadDirectory . $assethash, $content);
// ...
//unlock asset db
$pdo->exec("UNLOCK TABLES"); //unlock since we are done with sensitive asset stuff
// ...
if (isPlaceUsingRender($iteminfo->id))
{
RenderPlace($iteminfo->id);
}
}
else
{
echo "Not Authorized to access this asset";
}
}
}
}
else if ($iteminfo->AssetTypeId == 10) //model
{
$content = gzdecode(file_get_contents('php://input'));
//TODO: implement a .RBXL parser
if (isAssetApproved($id) and !isAssetModerated($id)) //if the asset is approved and not moderated
{
if ($iteminfo->CreatorId == $user->id)
{
//generate new hash for the asset
$assethash = genAssetHash(16);
// ...
//upload directory
$uploadDirectory = $GLOBALS['assetCDNPath']; //directory where the assets are stored
// ...
if (file_put_contents($uploadDirectory . $assethash, $content))
{
unlink($uploadDirectory . $iteminfo->Hash); //attempt to delete old hash, if doesnt work oh well
//lock asset db
$pdo->exec("LOCK TABLES assets WRITE"); //lock since this stuff is sensitive
//change asset to use new hash
$s = $pdo->prepare("UPDATE assets SET Hash = :hash WHERE id = :id");
$s->bindParam(":hash", $assethash, PDO::PARAM_STR);
$s->bindParam(":id", $iteminfo->id, PDO::PARAM_INT);
$s->execute();
//unlock asset db
$pdo->exec("UNLOCK TABLES"); //unlock since we are done with sensitive asset stuff
RenderModel($iteminfo->id);
}
}
else
{
echo "Not Authorized to access this asset";
}
}
}
}

View File

@ -0,0 +1,81 @@
<?php
/*
Alphaland 2021
The purpose of this is to upload Images from studio
*/;
$name = $_GET['name'];
$description = $_GET['description'];
$genreTypeId = $_GET['genreTypeId']; //isnt used in this script, but keeping anyways
$allowComments = $_GET['allowComments'];
//fuckload of checks but since people are SUS we need them
if ($name && $description && $genreTypeId && $allowComments)
{
if ($name == "Image" && $description == "Image")
{
$content = file_get_contents('php://input'); //content uploaded
if ($content) //if content was uploaded
{
//allowed image types
$types = array('image/png', 'image/jpeg');
$mimetype = finfo_buffer(finfo_open(), $content, FILEINFO_MIME_TYPE);
if (in_array($mimetype, $types))
{
//generate new hash for the asset
$assethash = genAssetHash(16);
// ...
//upload directory
$uploadDirectory = $GLOBALS['thumbnailCDNPath']; //directory where the thumbs/images are stored
// ...
//move uploaded data
$success = file_put_contents($uploadDirectory . $assethash, $content);
// ...
//if data was moved successfully
if ($success != 0)
{
echo(
CreateAsset(
1, //AssetTypeId
0, //IconImageAssetId
NULL, //TargetId(not used atm)
NULL, //ProductType(idk what to do with this atm)
cleanInput($name), //Name
cleanInput($description), //Description
time(), //Created
time(), //Updated
$user->id, //CreatorId
0, //PriceInAlphabux
0, //Sales
false, //isPersonalServer
false, //IsNew
false, //IsForSale
true, //IsPublicDomain
false, //IsLimited
false, //IsLimitedUnique
(int)$allowComments, //IsCommentsEnabled
true, //IsApproved
false, //IsModerated
0, //Remaining
0, //MinimumMembershipLevel
0, //ContentRatingTypeId
0, //Favorited
0, //Visited
0, //MaxPlayers
0, //UpVotes
0, //DownVotes
$assethash, //Hash
NULL //ThumbHash
)
);
}
}
}
}
}

View File

@ -0,0 +1,76 @@
<?php
/*
Alphaland 2021
The purpose of this is to upload Meshes from studio
*/;
$name = $_GET['name'];
$description = $_GET['description'];
$genreTypeId = $_GET['genreTypeId']; //isnt used in this script, but keeping anyways
$allowComments = $_GET['allowComments'];
//fuckload of checks but since people are SUS we need them
if ($name && $description && $genreTypeId && $allowComments)
{
if ($name == "RenderMesh" && $description == "RenderMesh")
{
$content = file_get_contents('php://input'); //content uploaded
if ($content) //if content was uploaded
{
if (strpos($content, "version") !== false) //very small check to see if it contains keyword for meshes
{
//generate new hash for the asset
$assethash = genAssetHash(16);
// ...
//upload directory
$uploadDirectory = $GLOBALS['assetCDNPath']; //directory where the assets are stored
// ...
//move uploaded data
$success = file_put_contents($uploadDirectory . $assethash, $content);
// ...
//if data was moved successfully
if ($success != 0)
{
echo(
CreateAsset(
4, //AssetTypeId
0, //IconImageAssetId
NULL, //TargetId(not used atm)
NULL, //ProductType(idk what to do with this atm)
cleanInput($name), //Name
cleanInput($description), //Description
time(), //Created
time(), //Updated
$user->id, //CreatorId
0, //PriceInAlphabux
0, //Sales
false, //isPersonalServer
false, //IsNew
false, //IsForSale
true, //IsPublicDomain
false, //IsLimited
false, //IsLimitedUnique
(int)$allowComments, //IsCommentsEnabled
true, //IsApproved
false, //IsModerated
0, //Remaining
0, //MinimumMembershipLevel
0, //ContentRatingTypeId
0, //Favorited
0, //Visited
0, //MaxPlayers
0, //UpVotes
0, //DownVotes
$assethash, //Hash
NULL //ThumbHash
)
);
}
}
}
}
}

View File

@ -0,0 +1,77 @@
<?php
/*
Alphaland 2021
The purpose of this is to upload MeshParts from studio
*/;
$name = $_GET['name'];
$description = $_GET['description'];
$genreTypeId = $_GET['genreTypeId']; //isnt used in this script, but keeping anyways
$allowComments = $_GET['allowComments'];
//fuckload of checks but since people are SUS we need them
if ($name && $description && $genreTypeId && $allowComments)
{
if ($description == "MeshPart")
{
$content = file_get_contents('php://input'); //content uploaded
if ($content) //if content was uploaded
{
$decodedcontent = gzdecode($content); //decode the data
if (strpos($decodedcontent, "<roblox!") !== false) //very small check to see if it contains keyword for serialized data
{
//generate new hash for the asset
$assethash = genAssetHash(16);
// ...
//upload directory
$uploadDirectory = $GLOBALS['assetCDNPath']; //directory where the assets are stored
// ...
//move uploaded data
$success = file_put_contents($uploadDirectory . $assethash, $decodedcontent);
// ...
//if data was moved successfully
if ($success != 0)
{
echo(
CreateAsset(
40, //AssetTypeId
0, //IconImageAssetId
NULL, //TargetId(not used atm)
NULL, //ProductType(idk what to do with this atm)
cleanInput($name), //Name
cleanInput($description), //Description
time(), //Created
time(), //Updated
$user->id, //CreatorId
0, //PriceInAlphabux
0, //Sales
false, //isPersonalServer
false, //IsNew
false, //IsForSale
true, //IsPublicDomain
false, //IsLimited
false, //IsLimitedUnique
(int)$allowComments, //IsCommentsEnabled
true, //IsApproved
false, //IsModerated
0, //Remaining
0, //MinimumMembershipLevel
0, //ContentRatingTypeId
0, //Favorited
0, //Visited
0, //MaxPlayers
0, //UpVotes
0, //DownVotes
$assethash, //Hash
NULL //ThumbHash
)
);
}
}
}
}
}

View File

@ -0,0 +1,147 @@
<?php
/*
Alphaland 2021
The purpose of this is to upload SolidModels (Unions) from studio, since studio does not serialize the actual Union
*/;
$assetTypeName = $_GET['assetTypeName'];
$name = $_GET['name'];
$description = $_GET['description'];
$isPublic = $_GET['isPublic']; //isnt used in this script, but keeping anyways
$genreTypeId = $_GET['genreTypeId']; //isnt used in this script, but keeping anyways
$allowComments = $_GET['allowComments'];
//fuckload of checks but since people are SUS we need them
if ($assetTypeName && $name && $isPublic && $allowComments)
{
if (!$description)
{
$description = "";
}
$offset = array_search($assetTypeName, assetTypeArray());
if (!$offset == 0) //assetTypeName valid
{
if ($assetTypeName == "SolidModel") //restricting to solidmodel
{
$content = file_get_contents('php://input'); //content uploaded
if ($content) //if content was uploaded
{
$decodedcontent = gzdecode($content); //decode the data
if (strpos($decodedcontent, "<roblox!") !== false && strpos($decodedcontent, "PartOperationAsset") !== false) //very small check to see if its actually a valid roblox asset and a solidmodel (very hard to guess this is happening in the backend, so fine for now)
{
//generate new hash for the asset
$assethash = genAssetHash(16);
// ...
//upload directory
$uploadDirectory = $GLOBALS['assetCDNPath']; //directory where the assets are stored
// ...
//move uploaded data
$success = file_put_contents($uploadDirectory . $assethash, $decodedcontent);
// ...
//if data was moved successfully
if ($success != 0)
{
//add asset to db and return the id //(int)price //(int)$isPublic
// v V
echo (CreateAsset($offset, 0, "TargetIdNotUsedHere", NULL, $name, $description, time(), time(), $user->id, 0, 0, 0, 0, 0, 1, 0, 0, (int)$allowComments, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, $assethash, NULL));
// ...
}
// ...
}
}
}
else if ($assetTypeName == "Model")
{
if (strlen($name) < 50 && strlen($name) > 3 && strlen($description) < 1024)
{
if ($isPublic == "true")
{
$isPublic = true;
}
else
{
$isPublic = false;
}
if ($allowComments == "true")
{
$allowComments = true;
}
else
{
$allowComments = false;
}
$content = file_get_contents('php://input'); //content uploaded
if ($content) //if content was uploaded
{
$decodedcontent = gzdecode($content); //decode the data
//generate new hash for the asset
$assethash = genAssetHash(16);
// ...
//upload directory
$uploadDirectory = $GLOBALS['assetCDNPath']; //directory where the assets are stored
// ...
//move uploaded data
$success = file_put_contents($uploadDirectory . $assethash, $decodedcontent);
// ...
//if data was moved successfully
if ($success != 0)
{
//add asset to db and return the id //(int)$isPublic
//
$newitem = CreateAsset(
$offset, //AssetTypeId
0, //IconImageAssetId
NULL, //TargetId(not used atm)
NULL, //ProductType(idk what to do with this atm)
cleanInput($name), //Name
cleanInput($description), //Description
time(), //Created
time(), //Updated
$user->id, //CreatorId
0, //PriceInAlphabux
0, //Sales
false, //isPersonalServer
false, //IsNew
$isPublic, //IsForSale
$isPublic, //IsPublicDomain
false, //IsLimited
false, //IsLimitedUnique
$allowComments, //IsCommentsEnabled
true, //IsApproved
false, //IsModerated
0, //Remaining
0, //MinimumMembershipLevel
0, //ContentRatingTypeId
0, //Favorited
0, //Visited
0, //MaxPlayers
0, //UpVotes
0, //DownVotes
$assethash, //Hash
NULL //ThumbHash
);
// ...
if (!RenderModel($newitem))
{
RenderModel($newitem); //if first fail do it again
}
giveItem($user->id, $newitem);
}
}
}
}
}
}

View File

@ -0,0 +1,54 @@
<?php
$games_html = "";
$games = getAllGames($user->id)->fetchAll(PDO::FETCH_ASSOC);
foreach ($games as $game)
{
$placethumbnail = handleGameThumb($game[id]);
$games_html .= <<<EOT
<li>
<div class="studio-place-card text-center" style="cursor: pointer;" onclick="updateGame({$game[id]})">
<a href="#">
<div class="studio-place-card-img">
<img class="img-fluid" src="{$placethumbnail}">
</div>
<p class="no-overflow">{$game[Name]}</p>
</a>
</div>
</li>
EOT;
}
$body = <<<EOT
<div class="container mt-2">
<h5>Save as:</h5>
<hr>
<div class="catalog-container">
<ul>
{$games_html}
</ul>
</div>
</div>
<script>
function updateGame(id)
{
if (window.external.SaveUrl('https://www.alphaland.cc/Studio/Data/UploadData?id=' + id + '\''))
{
alert("Uploaded");
window.close();
}
else
{
alert("Failed to Upload");
window.close();
}
}
</script>
EOT;
pageHandler();
$ph->navbar = "";
$ph->footer = "";
$ph->pageTitle("Upload");
$ph->body = $body;
$ph->output();

View File

@ -0,0 +1,133 @@
<?php
$owned = $pdo->prepare("SELECT * FROM assets WHERE AssetTypeId = 10 AND CreatorId = :cid ORDER BY created DESC");
$owned->bindParam(":cid", $user->id, PDO::PARAM_INT);
$owned->execute();
$owned = $owned->fetchAll(PDO::FETCH_ASSOC);
$assets = "";
foreach($owned as $asset)
{
$assets .= '
<li>
<div class="studio-upload-card text-center" style="cursor: pointer;width: 152px;height: 185px" onclick="updateAsset('.$asset['id'].')">
<a>
<div class="studio-upload-card-img">
<img class="img-fluid" style="width: 150px;height: 150px" src="'.getAssetRender($asset['id']).'">
</div>
<p class="no-overflow">'.getAssetInfo($asset['id'])->Name.'</p>
</a>
</div>
</li>
';
}
$body = <<<EOT
<div class="container mt-2" id="update_model_dialog">
<h5>Upload Model to Alphaland:</h5>
<hr>
<div class="catalog-container">
<ul>
<li>
<div class="studio-upload-card text-center" style="cursor: pointer;" onclick="showNewModelDialog()">
<a>
<div class="studio-upload-card-img">
<img class="img-fluid" src="/alphaland/cdn/imgs/addmodelicon.png">
</div>
<p class="no-overflow">Create New</p>
</a>
</div>
</li>
{$assets}
</ul>
</div>
</div>
<div id="new_model_dialog" style="width:60%;margin:auto;display:none;">
<div id = "error_alert" class="alert alert-danger" role="alert" style="display:none;"></div>
<h5 class="mt-2">Create Model:</h5>
<hr>
<label>Model Name</label>
<input class="form-control mb-3" id="model_name" placeholder="Model Name"></input>
<label>Model Description</label>
<textarea class="form-control mb-2" id="model_description" placeholder="Model Description" style="height:7rem;max-height:7rem;"></textarea>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="copylocked">
<label class="form-check-label" for="copylocked">Copylocked</label>
</div>
<button class="btn btn-danger float-right" onclick="newAsset()">Upload</button>
</div>
<script>
function checkParameters(name, description)
{
var message = "";
if (name.length > 50)
{
message = "Name cannot be more than 50 characters";
}
else if (name.length < 3)
{
message = "Name must be more than 3 characters";
}
else if (description.length > 1024)
{
message = "Description cannot be more than 1024 characters"
}
if (message)
{
$("#error_alert").text(message);
$("#error_alert").show();
setTimeout(function()
{
$("#error_alert").hide();
}, 3000);
return false; //issue
}
return true; //no issues
}
function showNewModelDialog()
{
$("#update_model_dialog").hide();
$("#new_model_dialog").show();
}
function updateAsset(assetid)
{
window.external.WriteSelection().Upload('https://www.alphaland.cc/Studio/Data/UploadData?id=' + assetid + '\'');
alert("Updated Model");
window.close();
}
function newAsset()
{
var modelname = $("#model_name").val();
var modeldescription = $("#model_description").val();
var ispublic = "true";
if ($('#copylocked').is(":checked"))
{
ispublic = "false";
}
if (checkParameters(modelname, modeldescription))
{
window.external.WriteSelection().Upload("https://www.alphaland.cc/Studio/IDE/Publish/uploadnewasset?assetTypeName=Model&name="+modelname+"&description="+modeldescription+"&isPublic="+ispublic+"&allowComments=false");
alert("Created Model");
window.close();
}
}
</script>
EOT;
pageHandler();
$ph->navbar = "";
$ph->footer = "";
$ph->studio = true; //force default theme (light)
$ph->body = $body;
$ph->pageTitle("Upload");
$ph->output();

View File

@ -0,0 +1,148 @@
<?php
$body = <<<EOT
<form>
<div class="container">
<div style="text-align:center;margin-top:8px;">
<h4>Toolbox BETA</h4>
<label>Search Toolbox</label>
<input id="search_input" style="width:74%;height:32px;"></input>
<button type="button" class="toolbox-btn" onclick='loadMore(1, $("#search_input").val())' style="width:24%;height:32px;">Search</button>
</div>
<div style="text-align:center;">
<select onchange="setType(this.value)" style="width:98.6%;margin-top:6px;height:32px;">
<option value="0">My Models</option>
<option value="1">Free Models</option>
</select>
</div>
</div>
</form>
<hr>
<div class="container">
<div class="toolbox-container">
<ul id="item_container">
</ul>
</div>
</div>
<hr>
<div class="container text-center">
<button class="toolbox-btn" id="load_button">Load More</button>
</div>
<script>
/*
Alphaland Ghetto Toolbox 2021
Luckily MOST of jquery works with qt 4
0 = Current User Models
1 = Public User Models
*/
var category = "";
var api = "https://www.alphaland.cc/studio/ide/toolbox/items";
function insertAsset(assetid)
{
window.external.Insert("https://www.alphaland.cc/asset/?id="+assetid);
}
function setType(type)
{
type = parseInt(type)
switch(type)
{
case 0: //user models
category = "UserModels";
break;
case 1: //public user models
category = "FreeModels";
break;
default:
alert("Error Occurred");
break;
}
loadMore(1);
}
function loadMore(page, keyword)
{
if (keyword === undefined) //HACK since old js sucks
{
keyword = "";
}
var html = '<li>';
html += '<div class="studio-tooblox-card text-center" style="cursor: pointer;" onclick="insertAsset({id})">';
html += '<a>';
html += '<div class="studio-tooblox-card-img">';
html += '<img class="img-fluid" style="width: 124px;height: 69px" src="{thumbnail}">';
html += '</div>';
html += '<p class="no-overflow">{name}</p>';
html += '</a>';
html += '</div>';
html += '</li>';
toolboxPageHelper("loadMore", api, "#item_container", "#load_button", html, page, 6, keyword, "No Models", "&category="+category)
}
function toolboxPageHelper(callName, api, container, buttonid, html, page, limit, keyword, message, args)
{
getJSONCDS(api + '?limit=' + limit + '&page=' + page + '&keyword=' + keyword + args)
.done(function(jsonData) {
var showButton = false;
var pageCount = jsonData.pageCount;
var pageResults = jsonData.pageResults;
var currentPage = page;
var nextPage = currentPage + 1;
var previousPage = currentPage - 1;
var previousHtml = "";
$(buttonid).hide();
if (nextPage > pageCount) {
nextPage = pageCount;
}
if (previousPage == 0) {
previousPage = 1;
}
if (pageCount > 1) {
showButton = true;
}
if (showButton)
{
$(buttonid).show();
if (currentPage == pageCount)
{
$(buttonid).hide();
}
if (currentPage > 1)
{
previousHtml = $(container).html();
}
$(buttonid).attr("onclick",callName + "(" + nextPage + ")");
}
$(container).html(previousHtml + parseHtml(html, pageResults, jsonData, message));
$("html, body").animate({ scrollTop: $(document).height() }, "fast");
});
}
setType(0); //default my models
console.log("Toolbox Initialized");
</script>
EOT;
pageHandler();
$ph->navbar = "";
$ph->footer = "";
$ph->studio = true; //force default theme (light)
$ph->pageTitle("Toolbox");
$ph->body = $body;
$ph->output();

View File

@ -0,0 +1,100 @@
<?php
/*
Alphaland 2021
*/
//headers
header("Access-Control-Allow-Origin: https://www.alphaland.cc");
header("access-control-allow-credentials: true");
header('Content-Type: application/json');
//get params
$category = $_GET['category'];
$creatorid = $_GET['creatorId'];
$page = $_GET['page'];
$limit = $_GET['limit'];
$keyword = substr((string)$_GET['keyword'], 0, 32); //32 limit
$keywordq = '%'.$keyword.'%'; //query
if (!$category)
{
http_response_code(400);
}
if (!$creatorid)
{
$creatorid = $user->id;
}
//initial checks
if (!$limit || !$page)
{
http_response_code(400);
}
if ($page < 1 || $limit < 1)
{
http_response_code(400);
}
//queries
if ($category == "FreeModels")
{
$query = "SELECT * FROM assets WHERE AssetTypeId = 10 AND name LIKE :u AND isPublicDomain = 1 ORDER BY created DESC";
}
else if ($category == "UserModels")
{
$query = "SELECT * FROM assets WHERE AssetTypeId = 10 AND name LIKE :u AND CreatorId = ".$creatorid." ORDER BY created DESC";
}
else
{
http_response_code(400);
}
//count how many shouts without offset/limit
$itemcount = $pdo->prepare($query);
$itemcount->bindParam(':u', $keywordq, PDO::PARAM_STR);
$itemcount->execute();
$itemcount = $itemcount->rowCount();
//data for pages
$total = $itemcount;
$pages = ceil($total / $limit);
$offset = ($page - 1) * $limit;
// Prepare the paged query
$items = $pdo->prepare($query . ' LIMIT :limit OFFSET :offset');
$items->bindParam(':u', $keywordq, PDO::PARAM_STR);
$items->bindParam(':limit', $limit, PDO::PARAM_INT);
$items->bindParam(':offset', $offset, PDO::PARAM_INT);
$items->execute();
$jsonData = array(
"pageCount" => $pages,
"pageResults" => (int)$items->rowCount()
);
foreach($items as $item)
{
$itemAssetId = $item['id'];
$itemInfo = getAssetInfo($itemAssetId);
$name = cleanOutput($itemInfo->Name);
$creatorid = $itemInfo->CreatorId;
$creator = getUsername($creatorid);
$render = getAssetRender($itemAssetId);
$items = array(
"id" => $itemAssetId,
"name" => $name,
"creatorId" => $creatorid,
"creator" => $creator,
"thumbnail" => $render
);
array_push($jsonData, $items);
}
// ...
die(json_encode($jsonData));

55
html/Studio/Places.php Normal file
View File

@ -0,0 +1,55 @@
<?php
if(!isLoggedIn())
{
redirect("../login?referral=" . "https://www.alphaland.cc/Studio/Places");
}
$games_html = "";
$games = getAllGames($user->id)->fetchAll(PDO::FETCH_ASSOC);
foreach ($games as $game)
{
$placethumbnail = handleGameThumb($game[id]);
$games_html .= <<<EOT
<li>
<div class="studio-place-card text-center" style="cursor: pointer;" onclick="openGame({$game[id]})">
<a href="#">
<div class="studio-place-card-img">
<img class="img-fluid" src="{$placethumbnail}">
</div>
<p class="no-overflow">{$game[Name]}</p>
</a>
</div>
</li>
EOT;
}
$body = <<<EOT
<div class="container mt-2">
<h5>My Places:</h5>
<hr>
<div class="catalog-container">
<ul>
{$games_html}
</ul>
</div>
</div>
<script>
function openGame(id)
{
if (!window.external.StartGame("","","game:Load('https://www.alphaland.cc/asset/?id=" + id + "') game:SetPlaceId(" + id + ")"))
{
alert("Failed to open place, please report this");
window.close();
}
}
</script>
EOT;
pageHandler();
$ph->navbar = "";
$ph->footer = "";
$ph->pageTitle("My Places");
$ph->body = $body;
$ph->output();

37
html/activate.php Normal file
View File

@ -0,0 +1,37 @@
<?php
$activation = new Alphaland\Users\Activation();
if ($activation->isUserActivated($user->id)) {
redirect("/");
}
$activationcode = $activation->getUserActivationCode($user->id);
$body = '
<div class="container-fluid" style="display: flex;justify-content: center;align-items: center;text-align: center;min-height: 100vh;">
<div class="container">
<div class="row marg-bot-15">
<div class="col-sm-12 marg-bot-15">
<div class="card marg-auto">
<div class="card-body">
<h4>Activation Required</h4>
<hr>
<h5>To play Alphaland, you must activate this account in the <a href=https://discord.gg/RDj4aVh8VS>Discord Server</a>.</h5>
<h5>After joining, send the activation code below in the activation channel and refresh this page.</h5>
<hr>
<code>'.$activationcode.'</code>
<hr>
<a href="logout"><button class="btn btn-sm btn-danger mb-1">Logout</button></a>
</div>
</div>
</div>
</div>
</div>
</div>';
pageHandler();
$ph->pageTitle("Activate");
$ph->footer = "";
$ph->navbar = "";
$ph->body = $body;
$ph->output();

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 859 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 860 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="100px" height="50px" viewBox="0 0 100 50" enable-background="new 0 0 100 50" xml:space="preserve">
<polyline fill="none" stroke="#4D4D4D" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
26.232,35.01 15.039,23.817 25.865,12.99 "/>
<polyline fill="none" stroke="#4D4D4D" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
73.693,35.69 85.578,23.805 74.083,12.31 "/>
</svg>

After

Width:  |  Height:  |  Size: 834 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

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