diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 9433b1f..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-SNZ_CORE.rbx*
-SNZ_SHARED.rbx*
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 6bcc077..2f1ac59 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -5,20 +5,14 @@
[
{
"type": "shell",
- "label": "Package Game (Core)",
- "command": "rojo build --output SNZ_CORE.rbxmx core.project.json",
-
- "group":
+ "label": "Upload Game",
+ "command": "powershell -ExecutionPolicy ByPass -File UploadGame.ps1",
+
+ "group":
{
"kind": "build",
"isDefault": true
}
- },
-
- {
- "type": "shell",
- "label": "Package Game (Shared)",
- "command": "rojo build --output SNZ_SHARED.rbxmx shared.project.json",
}
]
}
\ No newline at end of file
diff --git a/Bin/.gitignore b/Bin/.gitignore
new file mode 100644
index 0000000..2f1229f
--- /dev/null
+++ b/Bin/.gitignore
@@ -0,0 +1,350 @@
+## 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
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
\ No newline at end of file
diff --git a/Bin/BevelConverter/App.config b/Bin/BevelConverter/App.config
new file mode 100644
index 0000000..88fa402
--- /dev/null
+++ b/Bin/BevelConverter/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Bin/BevelConverter/BevelConverter.csproj b/Bin/BevelConverter/BevelConverter.csproj
new file mode 100644
index 0000000..82dd769
--- /dev/null
+++ b/Bin/BevelConverter/BevelConverter.csproj
@@ -0,0 +1,90 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {957A7717-A3CB-41B0-A17C-0E638017E915}
+ Exe
+ Properties
+ BevelConverter
+ BevelConverter
+ v4.5.2
+ 512
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ Packages\LZ4.dll
+
+
+ False
+ Packages\RobloxFileFormat.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+ Always
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Bin/BevelConverter/BevelConverter.sln b/Bin/BevelConverter/BevelConverter.sln
new file mode 100644
index 0000000..82bc89a
--- /dev/null
+++ b/Bin/BevelConverter/BevelConverter.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BevelConverter", "BevelConverter\BevelConverter.csproj", "{957A7717-A3CB-41B0-A17C-0E638017E915}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {957A7717-A3CB-41B0-A17C-0E638017E915}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {957A7717-A3CB-41B0-A17C-0E638017E915}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {957A7717-A3CB-41B0-A17C-0E638017E915}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {957A7717-A3CB-41B0-A17C-0E638017E915}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Bin/BevelConverter/Extensions/Formatting.cs b/Bin/BevelConverter/Extensions/Formatting.cs
new file mode 100644
index 0000000..5d0ced1
--- /dev/null
+++ b/Bin/BevelConverter/Extensions/Formatting.cs
@@ -0,0 +1,94 @@
+using System.Globalization;
+using System.Linq;
+
+// This global class defines extension methods to numeric types
+// where I don't want system globalization to come into play.
+
+public static class Format
+{
+ private const string decimalFmt = "0.00";
+ private static CultureInfo invariant => CultureInfo.InvariantCulture;
+
+ private static string filterNan(string value, string replace = decimalFmt)
+ {
+ if (value.ToLower() == "nan")
+ value = replace;
+
+ return value;
+ }
+
+ public static string ToInvariantString(this float value)
+ {
+ string result = value.ToString(decimalFmt, invariant);
+ return filterNan(result);
+ }
+
+ public static string ToInvariantString(this double value)
+ {
+ string result = value.ToString(decimalFmt, invariant);
+ return filterNan(result);
+ }
+
+ public static string ToInvariantString(this int value)
+ {
+ return value.ToString(invariant);
+ }
+
+ public static string ToInvariantString(this object value)
+ {
+ if (value is float)
+ {
+ float f = (float)value;
+ return f.ToInvariantString();
+ }
+ else if (value is double)
+ {
+ double d = (double)value;
+ return d.ToInvariantString();
+ }
+ else if (value is int)
+ {
+ int i = (int)value;
+ return i.ToInvariantString();
+ }
+ else
+ {
+ // Unhandled
+ return value.ToString();
+ }
+ }
+
+ public static float ParseFloat(string s)
+ {
+ return float.Parse(s, invariant);
+ }
+
+ public static double ParseDouble(string s)
+ {
+ return double.Parse(s, invariant);
+ }
+
+ public static int ParseInt(string s)
+ {
+ return int.Parse(s, invariant);
+ }
+
+ public static string FormatFloats(params float[] values)
+ {
+ string[] results = values
+ .Select(value => value.ToInvariantString())
+ .ToArray();
+
+ for (int i = 0; i < results.Length; i++)
+ {
+ string result = results[i];
+
+ while (result.Contains(".") && (result.EndsWith("0") || result.EndsWith(".")))
+ result = result.Substring(0, result.Length - 1);
+
+ results[i] = result;
+ }
+
+ return '[' + string.Join("][", results) + ']';
+ }
+}
\ No newline at end of file
diff --git a/Bin/BevelConverter/Extensions/RegistryHelper.cs b/Bin/BevelConverter/Extensions/RegistryHelper.cs
new file mode 100644
index 0000000..039b91b
--- /dev/null
+++ b/Bin/BevelConverter/Extensions/RegistryHelper.cs
@@ -0,0 +1,17 @@
+using System.IO;
+using Microsoft.Win32;
+
+public static class RegistryHelper
+{
+ public static RegistryKey GetSubKey(this RegistryKey key, params string[] path)
+ {
+ string constructedPath = Path.Combine(path);
+ return key.CreateSubKey(constructedPath, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryOptions.None);
+ }
+
+ public static string GetString(this RegistryKey key, string name)
+ {
+ var result = key.GetValue(name, "");
+ return result.ToString();
+ }
+}
\ No newline at end of file
diff --git a/Bin/BevelConverter/Geometry/Mesh.cs b/Bin/BevelConverter/Geometry/Mesh.cs
new file mode 100644
index 0000000..c44b953
--- /dev/null
+++ b/Bin/BevelConverter/Geometry/Mesh.cs
@@ -0,0 +1,410 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+using RobloxFiles.DataTypes;
+
+namespace BevelConverter
+{
+ public class Mesh
+ {
+ public int Version;
+
+ public int NumVerts = 0;
+ public List Verts;
+
+ public int NumFaces = 0;
+ public List Faces;
+
+ public ushort NumLODs = 0;
+ public List LODs;
+
+ private static Vector3 ReadVector3(BinaryReader reader)
+ {
+ float x = reader.ReadSingle(),
+ y = reader.ReadSingle(),
+ z = reader.ReadSingle();
+
+ return new Vector3(x, y, z);
+ }
+
+ private static void CheckDefaultLODs(Mesh mesh)
+ {
+ if (mesh.NumLODs == 0)
+ {
+ mesh.NumLODs = 2;
+ mesh.LODs = new List { 0, mesh.NumFaces };
+ }
+ }
+
+ private static void LoadGeometry_Ascii(StringReader reader, Mesh mesh)
+ {
+ string header = reader.ReadLine();
+
+ if (!header.StartsWith("version 1"))
+ throw new Exception("Expected version 1 header, got: " + header);
+
+ string version = header.Substring(8);
+ float vertScale = (version == "1.00" ? 0.5f : 1);
+
+ if (int.TryParse(reader.ReadLine(), out mesh.NumFaces))
+ mesh.NumVerts = mesh.NumFaces * 3;
+ else
+ throw new Exception("Expected 2nd line to be the polygon count.");
+
+ mesh.Faces = new List();
+ mesh.Verts = new List();
+
+ string polyBuffer = reader.ReadLine();
+ MatchCollection matches = Regex.Matches(polyBuffer, @"\[(.*?)\]");
+
+ int face = 0;
+ int index = 0;
+ int target = 0;
+
+ var vertex = new Vertex();
+
+ foreach (Match m in matches)
+ {
+ string vectorStr = m.Groups[1].ToString();
+
+ float[] coords = vectorStr.Split(',')
+ .Select(coord => Format.ParseFloat(coord))
+ .ToArray();
+
+ if (target == 0)
+ vertex.Position = new Vector3(coords) * vertScale;
+ else if (target == 1)
+ vertex.Normal = new Vector3(coords);
+ else if (target == 2)
+ vertex.UV = new Vector3(coords[0], 1 - coords[1], 0);
+
+ target = (target + 1) % 3;
+
+ if (target == 0)
+ {
+ mesh.Verts.Add(vertex);
+ vertex = new Vertex();
+
+ if (index % 3 == 0)
+ {
+ int v = face * 3;
+ int[] faceDef = new int[3] { v, v + 1, v + 2 };
+ mesh.Faces.Add(faceDef);
+ }
+ }
+ }
+
+ CheckDefaultLODs(mesh);
+ }
+
+ private static void LoadGeometry_Binary(BinaryReader reader, Mesh mesh)
+ {
+ byte[] binVersion = reader.ReadBytes(13);
+ var headerSize = reader.ReadUInt16();
+
+ var vertSize = reader.ReadByte();
+ var faceSize = reader.ReadByte();
+
+ if (mesh.Version >= 3)
+ {
+ var lodRangeSize = reader.ReadUInt16();
+ mesh.NumLODs = reader.ReadUInt16();
+ }
+
+ mesh.NumVerts = reader.ReadInt32();
+ mesh.NumFaces = reader.ReadInt32();
+
+ mesh.LODs = new List();
+ mesh.Faces = new List();
+ mesh.Verts = new List();
+
+ for (int i = 0; i < mesh.NumVerts; i++)
+ {
+ Vertex vert = new Vertex()
+ {
+ Position = ReadVector3(reader),
+ Normal = ReadVector3(reader),
+ UV = ReadVector3(reader)
+ };
+
+ if (vertSize > 36)
+ {
+ byte r = reader.ReadByte(),
+ g = reader.ReadByte(),
+ b = reader.ReadByte(),
+ a = reader.ReadByte();
+
+ int argb = (a << 24 | r << 16 | g << 8 | b);
+ vert.Color = Color.FromArgb(argb);
+ vert.HasColor = true;
+ }
+
+ mesh.Verts.Add(vert);
+ }
+
+ for (int i = 0; i < mesh.NumFaces; i++)
+ {
+ int[] face = new int[3];
+
+ for (int f = 0; f < 3; f++)
+ face[f] = reader.ReadInt32();
+
+ mesh.Faces.Add(face);
+ }
+
+ if (mesh.NumLODs > 0)
+ {
+ for (int i = 0; i < mesh.NumLODs; i++)
+ {
+ int lod = reader.ReadInt32();
+ mesh.LODs.Add(lod);
+ }
+ }
+ else
+ {
+ CheckDefaultLODs(mesh);
+ }
+ }
+
+ public void AddLod(Mesh lodMesh)
+ {
+ Verts.AddRange(lodMesh.Verts);
+
+ Faces.AddRange(lodMesh.Faces
+ .Select(face => face
+ .Select(i => i + NumVerts)
+ .ToArray()
+ )
+ );
+
+ NumVerts = Verts.Count;
+ NumFaces = Faces.Count;
+
+ LODs.Add(NumFaces);
+ NumLODs += 1;
+ }
+
+ public void Save(Stream stream)
+ {
+ const ushort HeaderSize = 16;
+ const byte VertSize = 40;
+ const byte FaceSize = 12;
+ const ushort LOD_Size = 4;
+
+ byte[] VersionHeader = Encoding.ASCII.GetBytes("version 3.00\n");
+
+ using (BinaryWriter writer = new BinaryWriter(stream))
+ {
+ writer.Write(VersionHeader);
+ writer.Write(HeaderSize);
+
+ writer.Write(VertSize);
+ writer.Write(FaceSize);
+ writer.Write(LOD_Size);
+
+ writer.Write(NumLODs);
+ writer.Write(NumVerts);
+ writer.Write(NumFaces);
+
+ for (int i = 0; i < NumVerts; i++)
+ {
+ Vertex vertex = Verts[i];
+
+ Vector3 pos = vertex.Position;
+ writer.Write(pos.X);
+ writer.Write(pos.Y);
+ writer.Write(pos.Z);
+
+ Vector3 norm = vertex.Normal;
+ writer.Write(norm.X);
+ writer.Write(norm.Y);
+ writer.Write(norm.Z);
+
+ Vector3 uv = vertex.UV;
+ writer.Write(uv.X);
+ writer.Write(uv.Y);
+ writer.Write(uv.Z);
+
+ if (vertex.HasColor)
+ {
+ Color color = vertex.Color;
+ writer.Write(color.R);
+ writer.Write(color.G);
+ writer.Write(color.B);
+ writer.Write(color.A);
+ }
+ else
+ {
+ writer.Write(-1);
+ }
+ }
+
+ for (int i = 0; i < NumFaces; i++)
+ {
+ int[] faces = Faces[i];
+
+ for (int f = 0; f < 3; f++)
+ {
+ int face = faces[f];
+ writer.Write(face);
+ }
+ }
+
+ for (int i = 0; i < NumLODs; i++)
+ {
+ int lod = LODs[i];
+ writer.Write(lod);
+ }
+ }
+ }
+
+ public static Mesh FromObjFile(string filePath)
+ {
+ string contents = File.ReadAllText(filePath);
+
+ Mesh mesh = new Mesh()
+ {
+ Version = 3,
+ Faces = new List(),
+ Verts = new List()
+ };
+
+ var posTable = new List();
+ var normTable = new List();
+
+ var vertexLookup = new Dictionary();
+
+ using (StringReader reader = new StringReader(contents))
+ {
+ string line;
+
+ while ((line = reader.ReadLine()) != null)
+ {
+ if (line.Length == 0)
+ continue;
+
+ string[] buffer = line.Split(' ');
+ string cmd = buffer[0];
+
+ if (cmd == "v" || cmd == "vn")
+ {
+ float x = float.Parse(buffer[1]),
+ y = float.Parse(buffer[2]),
+ z = float.Parse(buffer[3]);
+
+ Vector3 value = new Vector3(x, y, z);
+
+ var target = (cmd == "v" ? posTable : normTable);
+ target.Add(value);
+ }
+ else if (cmd == "f")
+ {
+ int[] face = new int[3];
+
+ for (int i = 0; i < 3; i++)
+ {
+ string faceDef = buffer[i + 1];
+ string[] indices = faceDef.Split('/');
+
+ int posId = int.Parse(indices[0]) - 1;
+ int normId = int.Parse(indices[2]) - 1;
+
+ string key = $"{posId}/{normId}";
+
+ if (!vertexLookup.ContainsKey(key))
+ {
+ int faceId = mesh.NumVerts++;
+ vertexLookup.Add(key, faceId);
+
+ Vertex vert = new Vertex()
+ {
+ Position = posTable[posId],
+ Normal = normTable[normId],
+ UV = new Vector3()
+ };
+
+ mesh.Verts.Add(vert);
+ }
+
+ face[i] = vertexLookup[key];
+ }
+
+ mesh.Faces.Add(face);
+ mesh.NumFaces++;
+ }
+ }
+ }
+
+ CheckDefaultLODs(mesh);
+ return mesh;
+ }
+
+ public static Mesh FromBuffer(byte[] data)
+ {
+ string file = Encoding.ASCII.GetString(data);
+
+ if (!file.StartsWith("version "))
+ throw new Exception("Invalid .mesh header!");
+
+ string versionStr = file.Substring(8, 4);
+ double version = Format.ParseDouble(versionStr);
+
+ Mesh mesh = new Mesh();
+ mesh.Version = (int)version;
+
+ IDisposable disposeThis;
+
+ if (mesh.Version == 1)
+ {
+ StringReader buffer = new StringReader(file);
+ LoadGeometry_Ascii(buffer, mesh);
+
+ disposeThis = buffer;
+ }
+ else if (mesh.Version == 2 || mesh.Version == 3)
+ {
+ MemoryStream stream = new MemoryStream(data);
+
+ using (BinaryReader reader = new BinaryReader(stream))
+ LoadGeometry_Binary(reader, mesh);
+
+ disposeThis = stream;
+ }
+ else
+ {
+ throw new Exception($"Unknown .mesh file version: {version}");
+ }
+
+ disposeThis.Dispose();
+ disposeThis = null;
+
+ return mesh;
+ }
+
+ public static Mesh FromStream(Stream stream)
+ {
+ byte[] data;
+
+ using (MemoryStream buffer = new MemoryStream())
+ {
+ stream.CopyTo(buffer);
+ data = buffer.ToArray();
+ }
+
+ return FromBuffer(data);
+ }
+
+ public static Mesh FromFile(string path)
+ {
+ using (FileStream meshStream = File.OpenRead(path))
+ {
+ return FromStream(meshStream);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bin/BevelConverter/Geometry/Vertex.cs b/Bin/BevelConverter/Geometry/Vertex.cs
new file mode 100644
index 0000000..cea73ca
--- /dev/null
+++ b/Bin/BevelConverter/Geometry/Vertex.cs
@@ -0,0 +1,15 @@
+using System.Drawing;
+using RobloxFiles.DataTypes;
+
+namespace BevelConverter
+{
+ public class Vertex
+ {
+ public Vector3 Position;
+ public Vector3 Normal;
+ public Vector3 UV;
+
+ public bool HasColor = false;
+ public Color Color;
+ }
+}
diff --git a/Bin/BevelConverter/Program.cs b/Bin/BevelConverter/Program.cs
new file mode 100644
index 0000000..0d4b80f
--- /dev/null
+++ b/Bin/BevelConverter/Program.cs
@@ -0,0 +1,288 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Windows.Forms;
+
+using RobloxFiles;
+using RobloxFiles.DataTypes;
+using RobloxFiles.XmlFormat;
+
+using Microsoft.Win32;
+
+namespace BevelConverter
+{
+ class Program
+ {
+ private const string uploadNewMesh = "https://data.roblox.com/ide/publish/UploadNewMesh";
+ private static string bevelCacheDir;
+
+ private static string studioCookies = "";
+ private static string xCsrfToken = "Fetch";
+
+ private static Random rng = new Random();
+
+ static void addNoise(ref float value)
+ {
+ float noise = (float)(-1e-6 + (rng.NextDouble() * 2e-6));
+ value += noise;
+ }
+
+ static Mesh CreateBevelMesh(Vector3 size, bool reupload = false)
+ {
+ byte[] baseMesh = Properties.Resources.Bevels;
+ Mesh bevels = Mesh.FromBuffer(baseMesh);
+
+ float sx = (size.X - 1f) / 2f,
+ sy = (size.Y - 1f) / 2f,
+ sz = (size.Z - 1f) / 2f;
+
+ if (reupload)
+ {
+ addNoise(ref sx);
+ addNoise(ref sy);
+ addNoise(ref sz);
+ }
+
+ foreach (Vertex vert in bevels.Verts)
+ {
+ Vector3 pos = vert.Position;
+
+ float x = pos.X;
+ x += (x >= 0 ? sx : -sx);
+
+ float y = pos.Y;
+ y += (y >= 0 ? sy : -sy);
+
+ float z = pos.Z;
+ z += (z >= 0 ? sz : -sz);
+
+ vert.Position = new Vector3(x, y, z);
+ }
+
+ return bevels;
+ }
+
+ static long UploadMesh(Mesh mesh, string name, string desc)
+ {
+ string uploadName = WebUtility.UrlEncode(name);
+ string uploadDesc = WebUtility.UrlEncode(desc);
+
+ string address = $"{uploadNewMesh}?name={uploadName}&description={uploadDesc}";
+ var request = WebRequest.Create(address) as HttpWebRequest;
+
+ request.Method = "POST";
+ request.ContentType = "*/*";
+ request.UserAgent = "RobloxStudio/WinInet";
+
+ request.Headers.Set("Cookie", studioCookies);
+ request.Headers.Set("X-CSRF-TOKEN", xCsrfToken);
+
+ using (Stream writeStream = request.GetRequestStream())
+ {
+ mesh.Save(writeStream);
+ writeStream.Close();
+ }
+
+ HttpWebResponse response = null;
+
+ try
+ {
+ var result = request.GetResponse();
+ response = result as HttpWebResponse;
+ }
+ catch (WebException e)
+ {
+ response = e.Response as HttpWebResponse;
+
+ if (response.StatusDescription.Contains("XSRF"))
+ {
+ // Update the X-CSRF-TOKEN.
+ xCsrfToken = response.Headers.Get("X-CSRF-TOKEN");
+
+ // Retry the request again.
+ return UploadMesh(mesh, name, desc);
+ }
+ else
+ {
+ throw e;
+ }
+ }
+
+ long assetId = -1;
+
+ using (Stream stream = response.GetResponseStream())
+ {
+ byte[] data;
+
+ using (MemoryStream buffer = new MemoryStream())
+ {
+ stream.CopyTo(buffer);
+ data = buffer.ToArray();
+ }
+
+ string strAssetId = Encoding.ASCII.GetString(data);
+ assetId = long.Parse(strAssetId);
+ }
+
+ return assetId;
+ }
+
+ static string ProcessInput(string input)
+ {
+ float[] xyz;
+
+ try
+ {
+ var inputData = input.Split('~', ',', ' ')
+ .Select(str => str.Trim())
+ .Where(str => str.Length > 0)
+ .Select(str => Format.ParseFloat(str));
+
+ if (inputData.Count() != 3)
+ throw new Exception();
+
+ xyz = inputData.ToArray();
+ input = Format.FormatFloats(xyz);
+ }
+ catch
+ {
+ Console.WriteLine("\tInvalid input: {0}", input);
+ return null;
+ }
+
+ string name = $"Bevel{input}";
+ const string desc = "[AUTO-GENERATED BEVEL MESH]";
+ string cached = Path.Combine(bevelCacheDir, $"{name}.txt");
+
+ bool exists = File.Exists(cached);
+ bool moderated = false;
+
+ if (exists)
+ {
+ string contents = File.ReadAllText(cached);
+ moderated = (contents.ToLower() == "moderated");
+ }
+
+ if (moderated || !exists)
+ {
+ Vector3 size = new Vector3(xyz);
+ Mesh mesh = CreateBevelMesh(size, moderated);
+
+ Console.WriteLine("\tUploading {0}...", name);
+ long assetId = UploadMesh(mesh, name, desc);
+
+ File.WriteAllText(cached, assetId.ToString());
+ }
+
+ string result = "rbxassetid://" + File.ReadAllText(cached);
+ Console.WriteLine(" Result -> {0} (copied to clipboard)", result);
+
+ return result;
+ }
+
+ static void ProcessFileArg(string filePath)
+ {
+ RobloxFile file = RobloxFile.Open(filePath);
+ Instance exportBin = file.FindFirstChild("ExportBin");
+
+ if (exportBin != null)
+ exportBin.Name = "BevelCache";
+ else
+ return;
+
+ Instance[] unions = exportBin.GetChildren()
+ .Where((child) => child.ClassName == "UnionOperation")
+ .OrderBy(child => child.Name)
+ .ToArray();
+
+ for (int i = 0; i < unions.Length; i++)
+ {
+ Instance union = unions[i];
+ string name = union.Name;
+
+ Console.WriteLine("Working on {0}... ({1}/{2})", union.Name, i, unions.Length);
+ union.ClassName = "MeshPart";
+
+ union.RemoveProperty("AssetId");
+ union.RemoveProperty("MeshData");
+ union.RemoveProperty("ChildData");
+ union.RemoveProperty("UsePartColor");
+
+ string meshId = ProcessInput(name);
+
+ if (meshId == null)
+ continue;
+
+ union.SetProperty("MeshId", meshId);
+ }
+
+ using (FileStream export = File.OpenWrite(filePath))
+ file.Save(export);
+
+ if (file is XmlRobloxFile)
+ Process.Start(filePath);
+
+ Console.WriteLine("Finished processing order!");
+ Console.WriteLine("Press any key to continue...");
+
+ Console.ReadKey();
+ Console.Clear();
+ }
+
+ [STAThread]
+ static void Main(string[] args)
+ {
+ string localAppData = Environment.GetEnvironmentVariable("LocalAppData");
+ bevelCacheDir = Path.Combine(localAppData, "BevelCache");
+
+ if (!Directory.Exists(bevelCacheDir))
+ Directory.CreateDirectory(bevelCacheDir);
+
+ RegistryKey robloxCookies = Registry.CurrentUser.GetSubKey
+ (
+ "SOFTWARE", "Roblox",
+ "RobloxStudioBrowser",
+ "roblox.com"
+ );
+
+ foreach (string name in robloxCookies.GetValueNames())
+ {
+ string cookie = robloxCookies.GetString(name);
+
+ int startIndex = cookie.IndexOf("COOK::<") + 7;
+ int endIndex = cookie.IndexOf('>', startIndex);
+
+ cookie = cookie.Substring(startIndex, endIndex - startIndex);
+
+ if (studioCookies.Length > 0)
+ studioCookies += "; ";
+
+ studioCookies += $"{name}={cookie}";
+ }
+
+ if (args.Length > 0)
+ {
+ string filePath = args[0];
+ ProcessFileArg(filePath);
+ }
+
+ Console.WriteLine("Enter bevel sizes in format: 'X ~ Y ~ Z' to generate them as .mesh files!");
+ Console.WriteLine(" (Also accepts format: 'X, Y, Z' and 'X Y Z')");
+
+ while (true)
+ {
+ Console.Write("> ");
+ string inputLine = Console.ReadLine();
+
+ if (inputLine == "exit")
+ break;
+
+ string assetId = ProcessInput(inputLine);
+ Clipboard.SetText(assetId);
+ }
+ }
+ }
+}
diff --git a/Bin/BevelConverter/Properties/AssemblyInfo.cs b/Bin/BevelConverter/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..4171a78
--- /dev/null
+++ b/Bin/BevelConverter/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("BevelConverter")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("BevelConverter")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("957a7717-a3cb-41b0-a17c-0e638017e915")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Bin/BevelConverter/Properties/Resources.Designer.cs b/Bin/BevelConverter/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..0f22542
--- /dev/null
+++ b/Bin/BevelConverter/Properties/Resources.Designer.cs
@@ -0,0 +1,83 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace BevelConverter.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BevelConverter.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Byte[].
+ ///
+ internal static byte[] BevelPart {
+ get {
+ object obj = ResourceManager.GetObject("BevelPart", resourceCulture);
+ return ((byte[])(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Byte[].
+ ///
+ internal static byte[] Bevels {
+ get {
+ object obj = ResourceManager.GetObject("Bevels", resourceCulture);
+ return ((byte[])(obj));
+ }
+ }
+ }
+}
diff --git a/Bin/BevelConverter/Properties/Resources.resx b/Bin/BevelConverter/Properties/Resources.resx
new file mode 100644
index 0000000..8e1d40b
--- /dev/null
+++ b/Bin/BevelConverter/Properties/Resources.resx
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ ..\Resources\BevelPart.rbxm;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\Bevels.mesh;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Bin/BevelConverter/Resources/BevelPart.rbxm b/Bin/BevelConverter/Resources/BevelPart.rbxm
new file mode 100644
index 0000000..6129f50
Binary files /dev/null and b/Bin/BevelConverter/Resources/BevelPart.rbxm differ
diff --git a/Bin/BevelConverter/Resources/Bevels.mesh b/Bin/BevelConverter/Resources/Bevels.mesh
new file mode 100644
index 0000000..eaea951
Binary files /dev/null and b/Bin/BevelConverter/Resources/Bevels.mesh differ
diff --git a/Client/Camera/Popper.lua b/Client/Camera/Popper.lua
index cd4d47b..50fca74 100644
--- a/Client/Camera/Popper.lua
+++ b/Client/Camera/Popper.lua
@@ -10,7 +10,8 @@ local PopperCam = {} -- Guarantees your players won't see outside the bounds of
local POP_RESTORE_RATE = 0.3
local MIN_CAMERA_ZOOM = 0.5
-local VALID_SUBJECTS = {
+local VALID_SUBJECTS =
+{
'Humanoid',
'VehicleSeat',
'SkateboardPlatform',
diff --git a/Client/Explosions/init.client.lua b/Client/Explosions/init.client.lua
index 18e35da..dbc4047 100644
--- a/Client/Explosions/init.client.lua
+++ b/Client/Explosions/init.client.lua
@@ -23,14 +23,14 @@ local function onDescendantAdded(exp)
local expObj = Instance.new("SphereHandleAdornment")
expObj.Adornee = expAdorn
expObj.Radius = exp.BlastRadius
- expObj.Color3 = Color3.new(1,0,0)
+ expObj.Color3 = Color3.new(1, 0, 0)
expObj.CFrame = cf
expObj.Parent = expAdorn
lifeTime = 1
if exp.BlastRadius > 1 then
- lifeTime = lifeTime - (1/exp.BlastRadius)
+ lifeTime = lifeTime - (1 / exp.BlastRadius)
end
else
local e = classicExp:Clone()
diff --git a/Client/ForceFields.client.lua b/Client/ForceFields.client.lua
index 814f3a2..2861428 100644
--- a/Client/ForceFields.client.lua
+++ b/Client/ForceFields.client.lua
@@ -2,15 +2,21 @@ local RunService = game:GetService("RunService")
local ffAdorns = workspace:WaitForChild("_ForceFieldAdorns")
local registry = {}
-local cycleStates = {}
+
+local cycleStates = setmetatable({}, { __mode = 'k'})
local cycles = 60
local function onChildAdded(child)
if child:IsA("SelectionBox") then
spawn(function ()
while not child.Adornee do
+ if not child:IsDescendantOf(ffAdorns) then
+ return
+ end
+
child.Changed:Wait()
end
+
registry[child] = child.Adornee
end)
end
@@ -24,24 +30,29 @@ end
local function update()
local now = tick()
- for adorn,adornee in pairs(registry) do
+
+ for adorn, adornee in pairs(registry) do
local model = adornee:FindFirstAncestorWhichIsA("Model")
- local key
+
if model then
- local key = model:GetFullName()
- local startTime = cycleStates[key]
+ local startTime = cycleStates[model]
+
if not startTime then
startTime = tick()
- cycleStates[key] = startTime
+ cycleStates[model] = startTime
end
- local cycle = math.floor(((now-startTime)*2) * cycles) % (cycles*2)
+
+ local cycle = math.floor(((now - startTime) * 2) * cycles) % (cycles * 2)
+
if cycle > cycles then
cycle = cycles - (cycle - cycles)
end
+
local invertCycle = cycles - cycle
- adorn.Color3 = Color3.new(cycle/cycles, 0, invertCycle/cycles)
+ adorn.Color3 = Color3.new(cycle / cycles, 0, invertCycle / cycles)
adorn.Transparency = 0
end
+
adorn.Visible = adornee:IsDescendantOf(workspace) and adornee.LocalTransparencyModifier < 1
end
end
@@ -51,5 +62,6 @@ for _,v in pairs(ffAdorns:GetChildren()) do
end
RunService.Heartbeat:Connect(update)
+
ffAdorns.ChildAdded:Connect(onChildAdded)
ffAdorns.ChildRemoved:Connect(onChildRemoved)
\ No newline at end of file
diff --git a/Client/FpsCap.client.lua b/Client/FpsCap.client.lua
index 00efa60..01e7628 100644
--- a/Client/FpsCap.client.lua
+++ b/Client/FpsCap.client.lua
@@ -1,17 +1,14 @@
-return function (script)
- local RunService = game:GetService("RunService")
- local TeleportService = game:GetService("TeleportService")
-
- spawn(function ()
- while RunService.RenderStepped:Wait() do
- if TeleportService:GetTeleportSetting("FPSCapTo30") then
- local t0 = tick()
- RunService.Heartbeat:Wait()
- debug.profilebegin("30 FPS Cap")
- repeat until (t0+0.0325) < tick()
- debug.profileend()
- end
- end
- end)
-
+local RunService = game:GetService("RunService")
+local TeleportService = game:GetService("TeleportService")
+
+while RunService.RenderStepped:Wait() do
+ if TeleportService:GetTeleportSetting("FPSCapTo30") then
+ local t0 = tick()
+ RunService.Heartbeat:Wait()
+
+ debug.profilebegin("30 FPS Cap")
+ repeat until (t0 + 0.0325) < tick()
+
+ debug.profileend()
+ end
end
\ No newline at end of file
diff --git a/Client/HumanoidLabels/init.client.lua b/Client/HumanoidLabels/init.client.lua
index 191d4f8..998ed1b 100644
--- a/Client/HumanoidLabels/init.client.lua
+++ b/Client/HumanoidLabels/init.client.lua
@@ -1,14 +1,16 @@
-local humanoids = {}
+local humanoids = setmetatable({}, { __mode = 'k' })
+
local player = game.Players.LocalPlayer
local pgui = player:WaitForChild("PlayerGui")
+
local healthBase = script:WaitForChild("Health")
local rs = game:GetService("RunService")
local farStudsOffset = Vector3.new(0,2,0)
local closeStudsOffset = Vector3.new(0,1,0)
-local farSize = UDim2.new(0,50,0,20)
-local closeSize = UDim2.new(0,100,0,30)
+local farSize = UDim2.new(0, 50, 0, 20)
+local closeSize = UDim2.new(0, 100, 0, 30)
local function isFinite(num)
return num == num and num ~= -1/0 and num ~= 1/0
@@ -100,18 +102,12 @@ local function setupHumanoid(h)
h.AncestryChanged:Connect(onAncestryChanged)
end
-local function recurse(obj)
- for _,v in pairs(obj:GetChildren()) do
- if v:IsA("Humanoid") then
- humanoids[v] = true
- else
- recurse(v)
- end
+for _,desc in pairs(workspace:GetDescendants()) do
+ if desc:IsA("Humanoid") then
+ humanoids[desc] = true
end
end
-recurse(workspace)
-
for h in pairs(humanoids) do
humanoids[h] = true
@@ -127,13 +123,8 @@ local function onDescendantAdded(child)
end
end
-local function onDescendantRemoved(child)
- if humanoids[child] then
- humanoids[child] = nil
- end
+for _,desc in pairs(workspace:GetDescendants()) do
+ onDescendantAdded(desc)
end
-recurse(workspace)
-
-workspace.DescendantAdded:connect(onDescendantAdded)
-workspace.DescendantRemoving:connect(onDescendantRemoved)
\ No newline at end of file
+workspace.DescendantAdded:Connect(onDescendantAdded)
\ No newline at end of file
diff --git a/Client/InputGateway.client.lua b/Client/InputGateway.client.lua
deleted file mode 100644
index a61ce51..0000000
--- a/Client/InputGateway.client.lua
+++ /dev/null
@@ -1,185 +0,0 @@
-local UserInputService = game:GetService("UserInputService")
-local ContextActionService = game:GetService("ContextActionService")
-local Debris = game:GetService("Debris")
-
-local gateway = script.Parent
-local tool = gateway.Parent
-local remote = gateway:WaitForChild("Gateway")
-local player = game.Players.LocalPlayer
-local mouse = player:GetMouse()
-local isActive = false
-
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Standard Input
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
-local function activate(active,cf)
- isActive = active
- remote:FireServer("SetActive",active,cf)
- while isActive do
- wait(.1)
- remote:FireServer("SetTarget",mouse.Hit)
- end
-end
-
-local function onKey(input)
- local keyCode = input.KeyCode.Name
- local down = (input.UserInputState.Name == "Begin")
- remote:FireServer("KeyEvent",keyCode,down)
-end
-
-local function onInputBegan(input,gameProcessed)
- if not gameProcessed then
- local name = input.UserInputType.Name
- if name == "MouseButton1" then
- activate(true,mouse.Hit)
- elseif name == "Touch" then
- wait(.1)
- local state = input.UserInputState.Name
- if state == "End" or state == "Cancel" then
- activate(true,mouse.Hit)
- end
- elseif name == "Gamepad1" then
- local keyCode = input.KeyCode.Name
- if keyCode == "ButtonR2" then
- activate(true,mouse.Hit)
- end
- elseif name == "Keyboard" then
- onKey(input)
- end
- end
-end
-
-local function onInputEnded(input,gameProcessed)
- if not gameProcessed and isActive then
- local name = input.UserInputType.Name
- if name == "MouseButton1" or name == "Touch" or name == "Gamepad1" then
- activate(false,mouse.Hit)
- elseif name == "Keyboard" then
- onKey(input)
- end
- end
-end
-
-UserInputService.InputBegan:Connect(onInputBegan)
-UserInputService.InputEnded:Connect(onInputEnded)
-
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Special case Input
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
-local mControlScheme = tool:WaitForChild("ControlScheme",5)
-
-if mControlScheme then
- local controlSchemeData = require(mControlScheme)
- local controlScheme = controlSchemeData.Buttons
- local activateContext = controlSchemeData.ActivateContext
- local keyEvent = tool:WaitForChild("KeyEvent")
- local callbacks = {}
-
- local hands = { L = "Left", R = "Right" }
- local handTypes = {"Bumper","Trigger","Joystick (Press)"}
-
- local schemeDocs =
- {
- Keyboard = {"Hold Left Mouse Button - " .. activateContext};
- Gamepad = {"Hold Right Trigger - " .. activateContext};
- }
-
- for key,data in pairs(controlScheme) do
- local down = false
- callbacks[key] = function (actionName,inputState,inputObject)
- if (inputState.Name == "Begin") and not down then
- down = true
- if data.Client then
- keyEvent:Fire(key,true)
- else
- remote:FireServer("KeyEvent",key,true)
- end
- elseif (inputState.Name == "End") and down then
- down = false
- if data.Client then
- keyEvent:Fire(key,false)
- else
- remote:FireServer("KeyEvent",key,false)
- end
- end
- end
-
- local xBtn = data.XboxButton:gsub("Button","")
- if #xBtn == 2 then
- local handId,hTypeId = xBtn:match("(%u)(%d)")
- local hand = hands[handId]
- local hType = handTypes[tonumber(hTypeId)]
- xBtn = hand .. " " .. hType
- else
- xBtn = "(" .. xBtn .. ")"
- end
- table.insert(schemeDocs.Keyboard,key .. " - " .. data.Label)
- table.insert(schemeDocs.Gamepad,xBtn .. " - " .. data.Label)
- end
-
- local currentSchemeDocMsg
-
- local function onLastInputTypeChanged(inputType)
- if currentSchemeDocMsg and not UserInputService.TouchEnabled and not controlSchemeData.HideControls then
- local schemeDoc
- if inputType.Name:find("Gamepad") then
- schemeDoc = "Gamepad"
- else
- schemeDoc = "Keyboard"
- end
- currentSchemeDocMsg.Text = schemeDoc .. " Controls:\n\n" .. table.concat(schemeDocs[schemeDoc],"\n")
- end
- end
-
- local diedCon
- local equipped = false
-
- local function onUnequipped()
- if equipped then
- equipped = false
- for key,data in pairs(controlScheme) do
- ContextActionService:UnbindAction(data.Label)
- end
- currentSchemeDocMsg:Destroy()
- currentSchemeDocMsg = nil
- end
- end
-
- local function onEquipped()
- if not equipped then
- equipped = true
- for key,data in pairs(controlScheme) do
- ContextActionService:BindAction(data.Label,callbacks[key],true,Enum.KeyCode[data.XboxButton])
- ContextActionService:SetTitle(data.Label,data.Label)
- end
- if UserInputService.TouchEnabled then
- spawn(function ()
- local playerGui = player:WaitForChild("PlayerGui")
- local contextActionGui = playerGui:WaitForChild("ContextActionGui")
- local contextButtonFrame = contextActionGui:WaitForChild("ContextButtonFrame")
- contextButtonFrame.Size = UDim2.new(3/8,0,3/8,0)
- contextButtonFrame.AnchorPoint = Vector2.new(1,1)
- contextButtonFrame.Position = UDim2.new(1,0,1,0)
- end)
- end
- currentSchemeDocMsg = Instance.new("Message")
- currentSchemeDocMsg.Parent = player
- onLastInputTypeChanged(UserInputService:GetLastInputType())
- if not diedCon then
- local char = tool.Parent
- if char then
- local humanoid = char:FindFirstChildWhichIsA("Humanoid")
- if humanoid then
- diedCon = humanoid.Died:Connect(onUnequipped)
- end
- end
- end
- end
- end
-
- tool.Equipped:Connect(onEquipped)
- tool.Unequipped:Connect(onUnequipped)
- UserInputService.LastInputTypeChanged:Connect(onLastInputTypeChanged)
-end
\ No newline at end of file
diff --git a/Client/LensFlare.client.lua b/Client/LensFlare.client.lua
index a1989b6..05bfdf4 100644
--- a/Client/LensFlare.client.lua
+++ b/Client/LensFlare.client.lua
@@ -2,9 +2,9 @@ local RunService = game:GetService("RunService")
local Lighting = game:GetService("Lighting")
local TeleportService = game:GetService("TeleportService")
-local c = workspace.CurrentCamera
+local camera = workspace.CurrentCamera
+local lensFlareNode = camera:FindFirstChild("LensFlareNode")
-local lensFlareNode = c:FindFirstChild("LensFlareNode")
if not lensFlareNode then
lensFlareNode = Instance.new("Part")
lensFlareNode.Name = "LensFlareNode"
@@ -12,7 +12,7 @@ if not lensFlareNode then
lensFlareNode.Anchored = true
lensFlareNode.CanCollide = false
lensFlareNode.Locked = true
- lensFlareNode.Parent = c
+ lensFlareNode.Parent = camera
end
local lenses =
@@ -37,12 +37,11 @@ local function projectRay(ray,length)
return Ray.new(origin,direction.Unit * length)
end
-local function computeSunOcclusion()
- local sunPos = Lighting:GetSunDirection()
- local cf = c.CFrame
+local function computeSunOcclusion(sunPos)
+ local cf = camera.CFrame
- if sunPos:Dot(cf.lookVector) > 0 then
- local sunView = c:WorldToViewportPoint(cf.p + sunPos)
+ if sunPos:Dot(cf.LookVector) > 0 then
+ local sunView = camera:WorldToViewportPoint(cf.Position + sunPos)
local visibility = 0
local total = 0
@@ -51,42 +50,48 @@ local function computeSunOcclusion()
local posX = math.floor(sunView.X + dx * 15)
local posY = math.floor(sunView.Y + dy * 15)
- local sunRay = c:ViewportPointToRay(posX, posY)
- sunRay = projectRay(sunRay,5000)
+ local sunRay = camera:ViewportPointToRay(posX, posY)
+ sunRay = projectRay(sunRay, 5000)
+
+ local hit, pos = workspace:FindPartOnRay(sunRay, camera)
- local hit,pos = workspace:FindPartOnRay(sunRay,c)
if not hit then
visibility = visibility + 1
end
+
total = total + 1
end
end
visibility = visibility / total
- return (1-visibility),sunView
+ return (1 - visibility), sunView
end
return 0
end
-local function asVector2(v3,...)
- return Vector2.new(v3.X,v3.Y),...
+local function asVector2(v3, ...)
+ return Vector2.new(v3.X, v3.Y), ...
end
local function update()
if TeleportService:GetTeleportSetting("ClassicSky") then
- local vpSize = c.ViewportSize
+ local vpSize = camera.ViewportSize
local sunDir = Lighting:GetSunDirection()
+
local sunWP = sunDir * 10e6
- local sunSP,inView = asVector2(c:WorldToViewportPoint(sunWP))
- local occlusion = inView and computeSunOcclusion() or 1
- if occlusion < 1 then
+ local sunSP, inView = asVector2(camera:WorldToViewportPoint(sunWP))
+
+ local occlusion = inView and computeSunOcclusion(sunDir) or 1
+
+ if occlusion < 1 and sunDir.Y > -0.1 then
local invSunSP = vpSize - sunSP
local enabled = (inView and occlusion < 1)
- local flareBrightness = math.sqrt(math.max(0,sunDir.y*4))
+ local flareBrightness = math.sqrt(math.max(0, sunDir.Y * 4))
- for i,lense in ipairs(lenses) do
+ for i, lense in ipairs(lenses) do
local radius = lense.Radius / 12
+
if not lense.Beam then
local a0 = Instance.new("Attachment")
lense.A0 = a0
@@ -114,14 +119,15 @@ local function update()
beam.Parent = lensFlareNode
end
- local lenseSP = invSunSP:lerp(sunSP,lense.Distance)
- local lenseWP = c:ViewportPointToRay(lenseSP.X,lenseSP.Y,1).Origin
- local lenseCF = CFrame.new(lenseWP,lenseWP - sunDir)
- lense.A0.CFrame = lenseCF * CFrame.new(-radius/2,0,0)
- lense.A1.CFrame = lenseCF * CFrame.new(radius/2,0,0)
+ local lenseSP = invSunSP:Lerp(sunSP, lense.Distance)
+ local lenseWP = camera:ViewportPointToRay(lenseSP.X, lenseSP.Y, 1).Origin
+ local lenseCF = CFrame.new(lenseWP, lenseWP - sunDir)
+
+ lense.A0.CFrame = lenseCF * CFrame.new(-radius / 2, 0, 0)
+ lense.A1.CFrame = lenseCF * CFrame.new( radius / 2, 0, 0)
end
- lensFlareNode.Parent = c
+ lensFlareNode.Parent = camera
return
end
end
@@ -129,6 +135,4 @@ local function update()
lensFlareNode.Parent = nil
end
-return function (script)
- RunService:BindToRenderStep("LensFlareUpdate",201,update)
-end
\ No newline at end of file
+RunService:BindToRenderStep("LensFlareUpdate", 201, update)
\ No newline at end of file
diff --git a/Client/Music.client.lua b/Client/Music.client.lua
index b1fde17..86605e3 100644
--- a/Client/Music.client.lua
+++ b/Client/Music.client.lua
@@ -1,5 +1,6 @@
local TeleportService = game:GetService("TeleportService")
-local gameMusic = workspace:WaitForChild("GameMusic",10)
+local gameMusic = workspace:WaitForChild("GameMusic", 10)
+
if gameMusic and TeleportService:GetTeleportSetting("AllowMusic") then
gameMusic:Play()
end
\ No newline at end of file
diff --git a/Client/Sky/Star.rbxmx b/Client/Sky/Star.rbxmx
index 3ef3671..a8d5c96 100644
--- a/Client/Sky/Star.rbxmx
+++ b/Client/Sky/Star.rbxmx
@@ -76,7 +76,7 @@
false
false
0
- Frame
+ Star
[null]
[null]
[null]
diff --git a/Client/Sky/init.client.lua b/Client/Sky/init.client.lua
index ac165b2..73bfd51 100644
--- a/Client/Sky/init.client.lua
+++ b/Client/Sky/init.client.lua
@@ -11,11 +11,11 @@ local UserInputService = game:GetService("UserInputService")
local midnight = 0
local day = 86400
-local hour = day/24
+local hour = day / 24
local sunRise = day * .25
local sunSet = day * .75
-local riseAndSetTime = hour/2
+local riseAndSetTime = hour / 2
local times =
{
@@ -63,7 +63,7 @@ end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local function r()
- return -1 + (math.random()*2)
+ return -1 + (math.random() * 2)
end
local lastTime = 0
@@ -75,11 +75,32 @@ local nightFrame = night:WaitForChild("NightFrame")
local star = script:WaitForChild("Star")
local shadowsOn = true
+local black = Color3.new()
-for i = 1, 500 do
+local toneMap do
+ toneMap = Instance.new("ColorCorrectionEffect")
+ toneMap.TintColor = Color3.new(1.25, 1.25, 1.25)
+ toneMap.Name = "LegacyToneMap"
+ toneMap.Brightness = 0.03
+ toneMap.Saturation = 0.07
+ toneMap.Contrast = -0.15
+ toneMap.Parent = Lighting
+
+ if Lighting.Ambient ~= black then
+ Lighting.OutdoorAmbient = Lighting.Ambient
+ Lighting.Ambient = black:Lerp(Lighting.Ambient, 0.5)
+ end
+
+ Lighting.GlobalShadows = true
+ Lighting.ShadowSoftness = 0.1
+end
+
+for i = 1, 3000 do
local bb = star:Clone()
+ local size = math.random(2, 6) / 2
bb.StudsOffsetWorldSpace = Vector3.new(r(), r(), r()).Unit * 2500
- bb.Size = UDim2.new(0, math.random(2, 5), 0, math.random(2, 5))
+ bb.Star.Transparency = (math.random(1, 4) - 1) / 4
+ -- bb.Size = UDim2.new(0, size, 0, size)
bb.Adornee = skyAdorn
bb.Parent = skyAdorn
end
@@ -104,8 +125,15 @@ local function updateSky()
Lighting.Ambient = Lighting.OutdoorAmbient
end
end
+
+ local sunDir = Lighting:GetSunDirection()
+ local globalLight = math.clamp((sunDir.Y + .033) * 10, 0, 1)
+
+ toneMap.Contrast = -0.15 * globalLight
+ toneMap.Saturation = 0.07 * globalLight
if TeleportService:GetTeleportSetting("ClassicSky") then
+ local camera = workspace.CurrentCamera
local seconds = Lighting:GetMinutesAfterMidnight() * 60
if seconds < 0 then
@@ -115,14 +143,14 @@ local function updateSky()
if seconds ~= lastTime then
local sunDir = game.Lighting:GetSunDirection()
local skyColor = linearSpline(seconds, times, colors)
+ nightFrame.BackgroundTransparency = globalLight
nightFrame.BackgroundColor3 = skyColor
- nightFrame.BackgroundTransparency = math.clamp((sunDir.Y + .033) * 10, 0, 1)
lastTime = seconds
end
- local sunDir = Lighting:GetSunDirection()
- skyAdorn.CFrame = CFrame.new(c.CFrame.p) * CFrame.new(Vector3.new(), sunDir)
- skyAdorn.Parent = (nightFrame.BackgroundTransparency < 1 and c or nil)
+
+ skyAdorn.CFrame = CFrame.new(camera.CFrame.Position) * CFrame.new(Vector3.new(), sunDir)
+ skyAdorn.Parent = (nightFrame.BackgroundTransparency < 1 and camera or nil)
else
skyAdorn.Parent = nil
end
diff --git a/Client/SunRays/init.client.lua b/Client/SunRays/init.client.lua
index 89000df..deef011 100644
--- a/Client/SunRays/init.client.lua
+++ b/Client/SunRays/init.client.lua
@@ -52,6 +52,7 @@ end
local function update()
if TeleportService:GetTeleportSetting("ClassicSky") then
local sunPos = Lighting:GetSunDirection()
+
if sunPos.Y >= -.1 then
local visibility, sunView = computeSunVisibility()
diff --git a/Server/Resources/InputGateway/Client.client.lua b/Server/Resources/InputGateway/Client.client.lua
index a61ce51..aa0d12a 100644
--- a/Server/Resources/InputGateway/Client.client.lua
+++ b/Server/Resources/InputGateway/Client.client.lua
@@ -13,36 +13,38 @@ local isActive = false
-- Standard Input
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-local function activate(active,cf)
+local function activate(active, cf)
isActive = active
- remote:FireServer("SetActive",active,cf)
+ remote:FireServer("SetActive", active, cf)
+
while isActive do
wait(.1)
- remote:FireServer("SetTarget",mouse.Hit)
+ remote:FireServer("SetTarget", mouse.Hit)
end
end
local function onKey(input)
local keyCode = input.KeyCode.Name
local down = (input.UserInputState.Name == "Begin")
- remote:FireServer("KeyEvent",keyCode,down)
+ remote:FireServer("KeyEvent", keyCode, down)
end
local function onInputBegan(input,gameProcessed)
if not gameProcessed then
local name = input.UserInputType.Name
+
if name == "MouseButton1" then
- activate(true,mouse.Hit)
+ activate(true, mouse.Hit)
elseif name == "Touch" then
wait(.1)
local state = input.UserInputState.Name
if state == "End" or state == "Cancel" then
- activate(true,mouse.Hit)
+ activate(true, mouse.Hit)
end
elseif name == "Gamepad1" then
local keyCode = input.KeyCode.Name
if keyCode == "ButtonR2" then
- activate(true,mouse.Hit)
+ activate(true, mouse.Hit)
end
elseif name == "Keyboard" then
onKey(input)
@@ -88,25 +90,25 @@ if mControlScheme then
for key,data in pairs(controlScheme) do
local down = false
- callbacks[key] = function (actionName,inputState,inputObject)
+ callbacks[key] = function (actionName, inputState, inputObject)
if (inputState.Name == "Begin") and not down then
down = true
if data.Client then
- keyEvent:Fire(key,true)
+ keyEvent:Fire(key, true)
else
- remote:FireServer("KeyEvent",key,true)
+ remote:FireServer("KeyEvent", key, true)
end
elseif (inputState.Name == "End") and down then
down = false
if data.Client then
keyEvent:Fire(key,false)
else
- remote:FireServer("KeyEvent",key,false)
+ remote:FireServer("KeyEvent", key, false)
end
end
end
- local xBtn = data.XboxButton:gsub("Button","")
+ local xBtn = data.XboxButton:gsub("Button", "")
if #xBtn == 2 then
local handId,hTypeId = xBtn:match("(%u)(%d)")
local hand = hands[handId]
@@ -115,8 +117,9 @@ if mControlScheme then
else
xBtn = "(" .. xBtn .. ")"
end
- table.insert(schemeDocs.Keyboard,key .. " - " .. data.Label)
- table.insert(schemeDocs.Gamepad,xBtn .. " - " .. data.Label)
+
+ table.insert(schemeDocs.Keyboard, key .. " - " .. data.Label)
+ table.insert(schemeDocs.Gamepad, xBtn .. " - " .. data.Label)
end
local currentSchemeDocMsg
@@ -150,10 +153,12 @@ if mControlScheme then
local function onEquipped()
if not equipped then
equipped = true
+
for key,data in pairs(controlScheme) do
ContextActionService:BindAction(data.Label,callbacks[key],true,Enum.KeyCode[data.XboxButton])
ContextActionService:SetTitle(data.Label,data.Label)
end
+
if UserInputService.TouchEnabled then
spawn(function ()
local playerGui = player:WaitForChild("PlayerGui")
@@ -164,9 +169,12 @@ if mControlScheme then
contextButtonFrame.Position = UDim2.new(1,0,1,0)
end)
end
+
currentSchemeDocMsg = Instance.new("Message")
currentSchemeDocMsg.Parent = player
+
onLastInputTypeChanged(UserInputService:GetLastInputType())
+
if not diedCon then
local char = tool.Parent
if char then
@@ -181,5 +189,6 @@ if mControlScheme then
tool.Equipped:Connect(onEquipped)
tool.Unequipped:Connect(onUnequipped)
+
UserInputService.LastInputTypeChanged:Connect(onLastInputTypeChanged)
end
\ No newline at end of file
diff --git a/Server/Resources/InputGateway/Server.server.lua b/Server/Resources/InputGateway/Server.server.lua
index 0dfbbc8..65f9104 100644
--- a/Server/Resources/InputGateway/Server.server.lua
+++ b/Server/Resources/InputGateway/Server.server.lua
@@ -20,9 +20,9 @@ local function onGatewayReceive(sendingPlayer, request, ...)
if request == "SetActive" then
local down, target = ...
- assert(typeof(target) == "CFrame","Expected CFrame")
+ assert(typeof(target) == "CFrame", "Expected CFrame")
- humanoid.TargetPoint = target.p
+ humanoid.TargetPoint = target.Position
if humanoid.Health > 0 and tool:IsDescendantOf(char) then
if down then
@@ -33,12 +33,14 @@ local function onGatewayReceive(sendingPlayer, request, ...)
end
elseif request == "SetTarget" then
local target = ...
- assert(typeof(target) == "CFrame","Expected CFrame")
- humanoid.TargetPoint = target.p
+ assert(typeof(target) == "CFrame", "Expected CFrame")
+ humanoid.TargetPoint = target.Position
elseif request == "KeyEvent" then
local key, down = ...
- assert(typeof(key) == "string","bad key cast")
- assert(typeof(down) == "boolean","bad down state cast")
+
+ assert(typeof(key) == "string", "Expected string")
+ assert(typeof(down) == "boolean", "Expected boolean")
+
keyEvent:Fire(key, down)
end
end
diff --git a/Server/Scripts/LightingConfig.server.lua b/Server/Scripts/LightingConfig.server.lua
deleted file mode 100644
index 9746e13..0000000
--- a/Server/Scripts/LightingConfig.server.lua
+++ /dev/null
@@ -1,25 +0,0 @@
-local CollectionService = game:GetService("CollectionService")
-local Lighting = game:GetService("Lighting")
-
-if not CollectionService:HasTag(Lighting, "ConfigApplied") then
- local toneMap = Instance.new("ColorCorrectionEffect")
- toneMap.TintColor = Color3.new(1.25, 1.25, 1.25)
- toneMap.Brightness = 0.03
- toneMap.Saturation = 0.07
- toneMap.Contrast = -0.15
-
- toneMap.Name = "LegacyToneMap"
- toneMap.Parent = Lighting
-
- local black = Color3.new()
-
- if Lighting.Ambient ~= black then
- Lighting.OutdoorAmbient = Lighting.Ambient
- Lighting.Ambient = black:Lerp(Lighting.Ambient, 0.5)
- end
-
- Lighting.GlobalShadows = true
- Lighting.ShadowSoftness = 0
-
- CollectionService:AddTag(Lighting, "ConfigApplied")
-end
\ No newline at end of file
diff --git a/Server/Scripts/LoadTools.server.lua b/Server/Scripts/LoadTools.server.lua
index 97c397e..88f3fe3 100644
--- a/Server/Scripts/LoadTools.server.lua
+++ b/Server/Scripts/LoadTools.server.lua
@@ -2,7 +2,7 @@ local ServerStorage = game:GetService("ServerStorage")
local StarterPack = game:GetService("StarterPack")
local Players = game:GetService("Players")
-local tools = ServerStorage:WaitForChild("Tools")
+local tools = ServerStorage:WaitForChild("StandardTools")
local loadTools = ServerStorage:FindFirstChild("LoadTools")
if loadTools then
diff --git a/Server/Scripts/Time.server.lua b/Server/Scripts/Time.server.lua
index e8c1e5a..c66b375 100644
--- a/Server/Scripts/Time.server.lua
+++ b/Server/Scripts/Time.server.lua
@@ -4,7 +4,7 @@ local loadTime = ServerStorage:FindFirstChild("LoadTime")
if loadTime and loadTime.Value then
while wait() do
- Lighting:SetMinutesAfterMidnight((tick()*5)%1440)
+ Lighting:SetMinutesAfterMidnight((tick() * 5) % 1440)
end
end
diff --git a/Shared/PlaceData.lua b/Shared/PlaceData.lua
index f5e2a7c..19ce35a 100644
--- a/Shared/PlaceData.lua
+++ b/Shared/PlaceData.lua
@@ -29,31 +29,35 @@ local creators =
["ROBLOX Halloween Paintball 2009"] = "Stealth Pilot";
}
+local placeData = {}
+
local function iterPageItems(pages)
return coroutine.wrap(function ()
local pageNum = 1
+
while true do
for _, item in ipairs(pages:GetCurrentPage()) do
coroutine.yield(item, pageNum)
end
+
if pages.IsFinished then
break
end
+
pages:AdvanceToNextPageAsync()
pageNum = pageNum + 1
end
end)
end
-local placeData = {}
-
for place in iterPageItems(places) do
if place.PlaceId ~= game.PlaceId then
if place.Name:lower():find("devtest") then
place.DevTest = true
end
+
place.Creator = creators[place.Name] or "ROBLOX"
- table.insert(placeData,place)
+ table.insert(placeData, place)
end
end
diff --git a/UI/ConsoleTweaks.client.lua b/UI/ConsoleTweaks.client.lua
index 29a9c67..60bc743 100644
--- a/UI/ConsoleTweaks.client.lua
+++ b/UI/ConsoleTweaks.client.lua
@@ -11,25 +11,25 @@ if GuiService:IsTenFootInterface() then
local ui = script.Parent
local rootFrame = ui:WaitForChild("RootFrame")
- local zoomControls = gui:WaitForChild("ZoomControls")
+ local zoomControls = ui:WaitForChild("ZoomControls")
zoomControls.Visible = false
- local backpack = gui:WaitForChild("Backpack")
+ local backpack = ui:WaitForChild("Backpack")
backpack.Position = UDim2.new(0, 0, 1, 0)
- local chat = gui:WaitForChild("Chat")
+ local chat = ui:WaitForChild("Chat")
chat.Visible = false
- local chatPadding = gui:WaitForChild("ChatPadding", 1)
+ local chatPadding = ui:WaitForChild("ChatPadding", 1)
if chatPadding then
chatPadding:Destroy()
end
- local safeChat = gui:WaitForChild("SafeChat")
+ local safeChat = ui:WaitForChild("SafeChat")
safeChat.Visible = false
- local health = gui:WaitForChild("Health")
+ local health = ui:WaitForChild("Health")
addUIScale(health, 1.5)
end
diff --git a/UI/Messages/Message.rbxmx b/UI/Messages/Message.rbxmx
index 0b5c0b5..ef1194e 100644
--- a/UI/Messages/Message.rbxmx
+++ b/UI/Messages/Message.rbxmx
@@ -9,9 +9,9 @@
true
- 0.4980392
- 0.4980392
- 0.4980392
+ 0.6
+ 0.6
+ 0.6
0.5
diff --git a/UI/Messages/Player.rbxmx b/UI/Messages/Player.rbxmx
index 55f856e..08a4dcc 100644
--- a/UI/Messages/Player.rbxmx
+++ b/UI/Messages/Player.rbxmx
@@ -9,9 +9,9 @@
true
- 0.5882353
- 0.5882353
- 0.5882353
+ 0.6
+ 0.6
+ 0.6
0.5
@@ -33,9 +33,9 @@
[null]
0
- 32
+ 30
0
- 5
+ 40
[null]
0
diff --git a/UI/Mouse/ClickToMove.client.lua b/UI/Mouse/ClickToMove.client.lua
index 5bd6bd4..8cd591a 100644
--- a/UI/Mouse/ClickToMove.client.lua
+++ b/UI/Mouse/ClickToMove.client.lua
@@ -90,7 +90,7 @@ local function rotateCameraTowardsGoal()
local rotation = math.min(0.01, abs)
local cfLocal = focus:toObjectSpace(cf)
- camera.CFrame = focus * CFrame.Angles(0, -rotation * ign, 0) * cfLocal
+ camera.CFrame = focus * CFrame.Angles(0, -rotation * sign, 0) * cfLocal
end
end
end
@@ -127,13 +127,15 @@ mouse.TargetFilter = workspace.CurrentCamera
local lastTarget
local lastTargetCanClick = false
+local adorn = Instance.new("Part", script)
+
local disk = Instance.new("CylinderHandleAdornment")
disk.Name = "Disk"
disk.Color3 = Color3.new(0,1,0)
disk.Radius = 1
disk.Height = 0.2
disk.Visible = false
-disk.Adornee = workspace.Terrain
+disk.Adornee = adorn
disk.Parent = script
local goalDisk = disk:Clone()
@@ -220,7 +222,7 @@ local function render3dAdorn()
disk.Visible = canRenderDisk(true)
if disk.Visible then
- disk.CFrame = CFrame.new(mouse.Hit.p) * DISK_OFFSET
+ disk.CFrame = CFrame.new(mouse.Hit.Position) * DISK_OFFSET
mouseIcon.Image = ICON_HOVER
elseif canClickTarget() then
mouseIcon.Image = ICON_CLICK
@@ -243,8 +245,9 @@ RunService.Heartbeat:Connect(render3dAdorn)
-- Click Action
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-local function onInputBegan(input,gameProcessed)
- local goal = mouse.Hit.p
+local function onInputBegan(input, gameProcessed)
+ local goal = mouse.Hit.Position
+
if not gameProcessed and canRenderDisk() and humanoid then
local name = input.UserInputType.Name
diff --git a/UI/SafeChat/AspectRatio.model.json b/UI/SafeChat/AspectRatio.model.json
new file mode 100644
index 0000000..25f1c96
--- /dev/null
+++ b/UI/SafeChat/AspectRatio.model.json
@@ -0,0 +1,9 @@
+{
+ "ClassName": "UIAspectRatioConstraint",
+
+ "Properties":
+ {
+ "AspectRatio": 1.33333,
+ "DominantAxis": "Height"
+ }
+}
\ No newline at end of file
diff --git a/UI/SafeChat/ChatButton.model.json b/UI/SafeChat/ChatButton.model.json
new file mode 100644
index 0000000..59e9682
--- /dev/null
+++ b/UI/SafeChat/ChatButton.model.json
@@ -0,0 +1,44 @@
+{
+ "ClassName": "ImageButton",
+
+ "Properties":
+ {
+ "AnchorPoint": [0, 1],
+ "BackgroundTransparency": 1,
+
+ "Position": [0.0202, 0, 0.7777, 0],
+ "Size": [0, 32, 0, 32],
+
+ "Image": "rbxassetid://991182833"
+ },
+
+ "Children":
+ [
+ {
+ "Name": "Click",
+ "ClassName": "Sound",
+
+ "Properties":
+ {
+ "SoundId": "rbxasset://sounds/switch.mp3"
+ }
+ },
+
+ {
+ "Name": "Hint",
+ "ClassName": "ImageLabel",
+
+ "Properties":
+ {
+ "AnchorPoint": [0.5, 0.75],
+ "BackgroundTransparency": 1,
+
+ "Position": [1, 5, 0, 0],
+ "Size": [0.75, 0, 0.75, 0],
+
+ "Image": "rbxasset://textures/ui/Settings/Help/XButtonDark@2x.png",
+ "Visible": false
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/UI/SafeChat/Click.model.json b/UI/SafeChat/Click.model.json
deleted file mode 100644
index d2c28b1..0000000
--- a/UI/SafeChat/Click.model.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "ClassName": "Sound",
-
- "Properties":
- {
- "SoundId": "rbxasset://sounds/switch.mp3"
- }
-}
\ No newline at end of file
diff --git a/UI/SafeChat/Hint.model.json b/UI/SafeChat/Hint.model.json
deleted file mode 100644
index 9f604bf..0000000
--- a/UI/SafeChat/Hint.model.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "ClassName": "ImageLabel",
-
- "Properties":
- {
- "AnchorPoint": [0.5, 0.75],
- "BackgroundTransparency": 1,
-
- "Position": [1, 5, 0, 0],
- "Size": [0.75, 0, 0.75, 0],
-
- "Image": "rbxasset://textures/ui/Settings/Help/XButtonDark@2x.png",
- "Visible": false
- }
-}
\ No newline at end of file
diff --git a/UI/SafeChat/SafeChat.client.lua b/UI/SafeChat/SafeChat.client.lua
index 9f1d290..4260f77 100644
--- a/UI/SafeChat/SafeChat.client.lua
+++ b/UI/SafeChat/SafeChat.client.lua
@@ -2,11 +2,14 @@ local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local GuiService = game:GetService("GuiService")
-local c = workspace.CurrentCamera
-local resUpdate = c:GetPropertyChangedSignal("ViewportSize")
+local camera = workspace.CurrentCamera
+local resUpdate = camera:GetPropertyChangedSignal("ViewportSize")
local safeChat = script.Parent
-local click = safeChat:WaitForChild("Click")
+local chatButton = safeChat:WaitForChild("ChatButton")
+
+local click = chatButton:WaitForChild("Click")
+local gamepadHint = chatButton:WaitForChild("Hint")
local IMG_CHAT = "rbxassetid://991182833"
local IMG_CHAT_DN = "rbxassetid://991182832"
@@ -18,21 +21,6 @@ local IMG_CHAT_OVR = "rbxassetid://991182834"
local mSafeChatTree = ReplicatedStorage:WaitForChild("SafeChat")
local safeChatTree = require(mSafeChatTree)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Button Positioning
-
-local IS_PHONE = c.ViewportSize.Y < 600
-
-local function onResolutionUpdate()
- local viewPort = c.ViewportSize
- local chatX = math.min(25,viewPort.Y/40)
- local chatY = (viewPort.X/viewPort.Y) * (viewPort.Y * 0.225)
- safeChat.Position = UDim2.new(0,chatX,1,-chatY)
-end
-
-onResolutionUpdate()
-resUpdate:Connect(onResolutionUpdate)
-
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Safe Chat Tree
@@ -59,22 +47,23 @@ end
local function deactivateRootTree()
isActivated = false
- safeChat.Image = IMG_CHAT
+ chatButton.Image = IMG_CHAT
+
recursivelyDeactivateTree(rootTree)
if GuiService.SelectedObject then
GuiService.SelectedObject = nil
- GuiService:RemoveSelectionGroup("SafechatNav")
+ GuiService:RemoveSelectionGroup("SafeChatNav")
end
end
local function activateRootTree()
isActivated = true
rootTree.Visible = true
- safeChat.Image = IMG_CHAT_DN
+ chatButton.Image = IMG_CHAT_DN
if UserInputService:GetLastInputType() == Enum.UserInputType.Gamepad1 then
- GuiService:AddSelectionParent("SafechatNav", safeChat)
+ GuiService:AddSelectionParent("SafeChatNav", safeChat)
GuiService.SelectedObject = safeChat
end
end
@@ -86,8 +75,8 @@ local function assembleTree(tree)
local currentBranch
for i, branch in ipairs(tree.Branches) do
- local label = branch.Label
local branches = branch.Branches
+ local label = branch.Label
local button = tempButton:Clone()
button.Name = label
@@ -105,7 +94,7 @@ local function assembleTree(tree)
end
currentBranch = button
- button.BackgroundColor3 = Color3.new(0.7,0.7,0.7)
+ button.BackgroundColor3 = Color3.new(0.7, 0.7, 0.7)
branchFrame.Visible = true
end
@@ -118,7 +107,7 @@ local function assembleTree(tree)
submit = false
end
end
-
+
if submit then
click:Play()
deactivateRootTree()
@@ -137,12 +126,6 @@ end
rootTree = assembleTree(safeChatTree)
rootTree.Parent = safeChat
-if IS_PHONE then
- local uiScale = Instance.new("UIScale")
- uiScale.Parent = rootTree
- uiScale.Scale = 0.7
-end
-
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Button State
@@ -152,20 +135,21 @@ local isHovering = false
do
local function onMouseEnter()
if not isActivated then
- safeChat.Image = IMG_CHAT_OVR
+ chatButton.Image = IMG_CHAT_OVR
end
isHovering = true
end
local function onMouseLeave()
if not isActivated then
- safeChat.Image = IMG_CHAT
+ chatButton.Image = IMG_CHAT
end
+
isHovering = false
end
local function onMouseDown()
- safeChat.Image = IMG_CHAT_DN
+ chatButton.Image = IMG_CHAT_DN
end
local function onMouseUp()
@@ -180,11 +164,11 @@ do
end
end
- safeChat.MouseEnter:Connect(onMouseEnter)
- safeChat.MouseLeave:Connect(onMouseLeave)
+ chatButton.MouseEnter:Connect(onMouseEnter)
+ chatButton.MouseLeave:Connect(onMouseLeave)
- safeChat.MouseButton1Up:Connect(onMouseUp)
- safeChat.MouseButton1Down:Connect(onMouseDown)
+ chatButton.MouseButton1Up:Connect(onMouseUp)
+ chatButton.MouseButton1Down:Connect(onMouseDown)
UserInputService.InputBegan:Connect(onInputBegan)
end
@@ -193,8 +177,6 @@ end
-- Gamepad Stuff
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-local gamepadHint = safeChat:WaitForChild("Hint")
-
if GuiService:IsTenFootInterface() then
gamepadHint.Visible = true
else
diff --git a/UI/SafeChat/init.meta.json b/UI/SafeChat/init.meta.json
index 882d8fd..ee3ed49 100644
--- a/UI/SafeChat/init.meta.json
+++ b/UI/SafeChat/init.meta.json
@@ -1,14 +1,11 @@
{
- "className": "ImageButton",
+ "className": "Frame",
"properties":
{
+ "Size": [1, 0, 1, 0],
"AnchorPoint": [0, 1],
- "BackgroundTransparency": 1,
-
- "Position": [0, 22, 0.75, 0],
- "Size": [0, 32, 0, 30],
-
- "Image": "rbxassetid://991182833"
+ "Position": [0, 0, 1, 0],
+ "BackgroundTransparency": 1
}
}
\ No newline at end of file
diff --git a/UI/Topbar/Config.lua b/UI/Topbar/Config.lua
new file mode 100644
index 0000000..042251a
--- /dev/null
+++ b/UI/Topbar/Config.lua
@@ -0,0 +1,56 @@
+return
+{
+ Style =
+ {
+ Font = "Cartoon";
+ AutoButtonColor = false;
+
+ BorderSizePixel = 0;
+ Size = UDim2.new(1, 0, 1, 0);
+
+ BackgroundColor3 = Color3.fromRGB(177, 177, 177);
+ BackgroundTransparency = 0.5;
+
+ TextSize = 14;
+ TextXAlignment = "Left";
+
+ TextTransparency = 0.3;
+ TextStrokeTransparency = 0.9;
+ };
+
+ TextColors =
+ {
+ Active = Color3.fromRGB( 77, 77, 77);
+ Inactive = Color3.fromRGB(156, 156, 156);
+ };
+
+ Verbs =
+ {
+ {
+ Name = "Tools";
+ Enabled = false;
+ };
+
+ {
+ Name = "Insert";
+ Enabled = false;
+ };
+
+ {
+ Name = "Fullscreen";
+ Enabled = true;
+ };
+
+ {
+ Name = "Help";
+ Label = "Help...";
+ Enabled = true;
+ };
+
+ {
+ Name = "Exit";
+ Label = " Exit";
+ Enabled = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/UI/Topbar/Topbar.client.lua b/UI/Topbar/Topbar.client.lua
index b5bff59..1fcda3d 100644
--- a/UI/Topbar/Topbar.client.lua
+++ b/UI/Topbar/Topbar.client.lua
@@ -1,74 +1,45 @@
+-------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Setup
+-------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+local Players = game:GetService("Players")
+local GuiService = game:GetService("GuiService")
+local RunService = game:GetService("RunService")
+local TeleportService = game:GetService("TeleportService")
+local UserInputService = game:GetService("UserInputService")
+local UserGameSettings = UserSettings():GetService("UserGameSettings")
+
local topbar = script.Parent
-local buttons =
-{
- Tools =
- {
- Label = "Tools";
- Enabled = false;
- Order = 1;
- };
+local ui = topbar.Parent
+local config = require(topbar:WaitForChild("Config"))
- Insert =
- {
- Label = "Insert";
- Enabled = false;
- Order = 2;
- };
+local style = config.Style
+local verbs = config.Verbs
+local textColors = config.TextColors
- Fullscreen =
- {
- Label = "Fullscreen";
- Enabled = true;
- Order = 3;
- };
+local buttons = {}
- Help =
- {
- Label = "Help...";
- Enabled = true;
- Order = 4;
- };
+for i, verb in ipairs(verbs) do
+ local name = verb.Name
+ local enabled = verb.Enabled
+ local label = verb.Label or name
- Exit =
- {
- Label = " Exit";
- Enabled = true;
- Order = 5;
- }
-}
-
-local BTN_COLOR = Color3.fromRGB(177, 177, 177)
-local TEXT_ACTIVE = Color3.fromRGB(77, 77, 77)
-local TEXT_INACTIVE = Color3.fromRGB(156, 156, 156)
-
-for name, data in pairs(buttons) do
local button = Instance.new("TextButton")
button.Name = name
- button.Active = data.Enabled
- button.LayoutOrder = data.Order
- button.Text = " " .. data.Label
+ button.LayoutOrder = i
+ button.Active = enabled
+ button.Text = " " .. label
- button.Font = "Cartoon"
- button.AutoButtonColor = false
+ for key, value in pairs(config.Style) do
+ button[key] = value
+ end
- button.BorderSizePixel = 0
- button.Size = UDim2.new(1, 0, 1, 0)
-
- button.BackgroundColor3 = BTN_COLOR;
- button.BackgroundTransparency = 0.5;
-
- button.TextSize = 14
- button.TextXAlignment = "Left"
-
- button.TextTransparency = 0.3;
- button.TextStrokeTransparency = 0.9;
-
- local textColor = (data.Enabled and TEXT_ACTIVE or TEXT_INACTIVE)
+ local textColor = (enabled and textColors.Active or textColors.Inactive)
button.TextStrokeColor3 = textColor
button.TextColor3 = textColor
- if data.Enabled then
+ if enabled then
local function onMouseEnter()
button.BackgroundTransparency = 0
end
@@ -81,5 +52,135 @@ for name, data in pairs(buttons) do
button.MouseLeave:Connect(onMouseLeave)
end
+ buttons[name] = button
button.Parent = topbar
-end
\ No newline at end of file
+end
+
+-------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Help Button
+-------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+local helpButton = buttons.Help
+
+local helpWindow = ui:WaitForChild("HelpWindow")
+local helpClose = helpWindow:WaitForChild("Close")
+
+local function onHelpActivated()
+ helpWindow.Visible = true
+end
+
+local function onHelpClosed()
+ helpWindow.Visible = false
+end
+
+helpClose.Activated:Connect(onHelpClosed)
+helpButton.Activated:Connect(onHelpActivated)
+
+-------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Fullscreen Button
+-------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+local player = Players.LocalPlayer
+local fullscreen = buttons.Fullscreen
+
+local function onFullscreenActivated()
+ if not player:FindFirstChild("FullcreenMsg") then
+ local msg = Instance.new("Message")
+ msg.Name = "FullscreenMsg"
+ msg.Text = "This button is just here for legacy aesthetics, and has no functionality."
+
+ if UserInputService.KeyboardEnabled then
+ msg.Text = msg.Text .. "\nPress F11 to toggle fullscreen!"
+ end
+
+ msg.Parent = player
+ wait(3)
+ msg:Destroy()
+ end
+end
+
+local function updateFullscreen()
+ local text = fullscreen.Text
+
+ if UserGameSettings:InFullScreen() then
+ fullscreen.Text = text:gsub("Full", "x Full")
+ else
+ fullscreen.Text = text:gsub("x ", "")
+ end
+end
+
+updateFullscreen()
+
+fullscreen.Activated:Connect(onFullscreenActivated)
+UserGameSettings.FullscreenChanged:Connect(updateFullscreen)
+
+-------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Exit Button
+-------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+local exitButton = buttons.Exit
+
+local gameJoin = ui:WaitForChild("GameJoin")
+local message = gameJoin:WaitForChild("Message")
+
+local exitOverride = gameJoin:WaitForChild("ExitOverride")
+local exitBuffer = "Continue holding down 'Back' to return to the menu.\nExiting in...\n%.1f"
+
+local function onExitActivated()
+ if not exitOverride.Visible then
+ exitOverride.Visible = true
+ message.Visible = false
+ gameJoin.Visible = true
+
+ TeleportService:Teleport(998374377)
+ end
+end
+
+local function processExitInput(input, gameProcessed)
+ if gameProcessed then
+ return
+ end
+
+ if input.KeyCode == Enum.KeyCode.ButtonSelect then
+ if exitOverride.Visible then
+ return
+ end
+
+ if gameJoin.Visible then
+ return
+ end
+
+ if not game:IsLoaded() then
+ return
+ end
+
+ local success = true
+
+ gameJoin.Visible = true
+ message.Size = exitOverride.Size
+
+ for i = 3, 0, -.1 do
+ if input.UserInputState ~= Enum.UserInputState.Begin then
+ success = false
+ break
+ end
+
+ message.Text = exitBuffer:format(i)
+ wait(.1)
+ end
+
+ if success then
+ onExitActivated()
+ else
+ gameJoin.Visible = false
+ end
+ end
+end
+
+if not GuiService:IsTenFootInterface() then
+ exitButton.Activated:Connect(onExitActivated)
+end
+
+UserInputService.InputBegan:Connect(processExitInput)
+
+-------------------------------------------------------------------------------------------------------------------------------------------------------------
\ No newline at end of file
diff --git a/UI/Topbar/init.meta.json b/UI/Topbar/init.meta.json
index 251e87b..5d996b8 100644
--- a/UI/Topbar/init.meta.json
+++ b/UI/Topbar/init.meta.json
@@ -4,7 +4,7 @@
"properties":
{
"BackgroundTransparency": 1,
- "Position": [0, 80, 0, 0],
+ "Position": [0, 50, 0, 0],
"Size": [0, 100, 0, 20]
}
}
\ No newline at end of file
diff --git a/UploadGame.ps1 b/UploadGame.ps1
new file mode 100644
index 0000000..800d609
--- /dev/null
+++ b/UploadGame.ps1
@@ -0,0 +1,18 @@
+$confirmation = Read-Host "Are you sure you want to update Super Nostalgia Zone? (y/n)"
+
+if ($confirmation -eq 'y')
+{
+ echo "Grabbing cookie..."
+
+ $regKey = "HKCU:\Software\Roblox\RobloxStudioBrowser\roblox.com"
+ $regVal = Get-ItemPropertyValue -Path $regKey -Name ".ROBLOSECURITY"
+ $cookie = [regex]::Match($regVal, "COOK::<([^>]*)>") | % { $_.Groups[1].Value }
+
+ echo "Uploading core..."
+ rojo upload --asset_id 1011800466 --cookie $cookie core.project.json
+
+ echo "Uploading shared..."
+ rojo upload --asset_id 1027421176 --cookie $cookie shared.project.json
+
+ echo Finished!
+}
\ No newline at end of file
diff --git a/core.project.json b/core.project.json
index 9db2e50..326a0de 100644
--- a/core.project.json
+++ b/core.project.json
@@ -1,54 +1,58 @@
{
- "name": "MainModule",
+ "name": "SNZ_CORE",
"tree":
{
- "$path": "core.lua",
-
- "ReplicatedFirst":
+ "$className": "Folder",
+
+ "MainModule":
{
- "$className": "Folder",
-
- "JoinScript":
+ "$path": "core.lua",
+
+ "ReplicatedFirst":
{
- "$path": "join.client.lua",
-
- "UI":
+ "$className": "Folder",
+ "JoinScript":
{
- "$path": "UI"
+ "$path": "join.client.lua",
+
+ "UI":
+ {
+ "$path": "UI"
+ }
}
- }
- },
-
- "ReplicatedStorage":
- {
- "$path": "Shared"
- },
-
- "ServerStorage":
- {
- "$path": "Server/Resources",
+ },
- "Tools":
+ "ReplicatedStorage":
{
- "$path": "Tools"
+ "$path": "Shared"
+ },
+
+ "ServerStorage":
+ {
+ "$path": "Server/Resources",
+
+ "StandardTools":
+ {
+ "$path": "Tools"
+ }
+ },
+
+ "ServerScriptService":
+ {
+ "$path": "Server/Scripts"
+ },
+
+ "StarterCharacterScripts":
+ {
+ "$path": "Player"
+ },
+
+ "StarterPlayerScripts":
+ {
+ "$path": "Client"
}
- },
-
- "ServerScriptService":
- {
- "$path": "Server/Scripts"
- },
-
- "StarterCharacterScripts":
- {
- "$path": "Player"
- },
-
- "StarterPlayerScripts":
- {
- "$path": "Client"
}
}
}
\ No newline at end of file
diff --git a/default.project.json b/default.project.json
index 783cf4e..11a680d 100644
--- a/default.project.json
+++ b/default.project.json
@@ -31,7 +31,7 @@
"$className": "ServerStorage",
"$path": "Server/Resources",
- "Tools":
+ "StandardTools":
{
"$path": "Tools"
}
@@ -41,7 +41,7 @@
{
"$className": "StarterGui",
- "UI [PREVIEW, DO NOT EDIT]":
+ "UI [PREVIEW]":
{
"$path": "UI",
diff --git a/join.client.lua b/join.client.lua
index b640d36..8401b82 100644
--- a/join.client.lua
+++ b/join.client.lua
@@ -1,4 +1,5 @@
local CollectionService = game:GetService("CollectionService")
+local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local ReplicatedFirst = game:GetService("ReplicatedFirst")
local TeleportService = game:GetService("TeleportService")
@@ -9,7 +10,7 @@ local StarterGui = game:GetService("StarterGui")
spawn(function ()
local function setCoreSafe(method, ...)
while not pcall(StarterGui.SetCore, StarterGui, method, ...) do
- wait()
+ RunService.Heartbeat:Wait()
end
end
@@ -39,17 +40,10 @@ if playerGui:FindFirstChild("ConnectingGui") then
playerGui.ConnectingGui:Destroy()
end
-local IS_PHONE = ui.AbsoluteSize.Y < 600
-local topbar = ui:WaitForChild("Topbar")
+local gameJoin = ui:WaitForChild("GameJoin")
-if IS_PHONE then
- local uiScale = Instance.new("UIScale")
- uiScale.Scale = 0.6
- uiScale.Parent = topbar
-end
-
-local messageGui = ui:WaitForChild("GameJoin")
-local message = messageGui:WaitForChild("Message")
+local message = gameJoin:WaitForChild("Message")
+local exitOverride = gameJoin:WaitForChild("ExitOverride")
local partWatch = nil
local partQueue = {}
@@ -60,96 +54,39 @@ local messageFormat = "Bricks: %d Connectors: %d"
---------------------------------------------------------------------
-local fakeLoadTime = TeleportService:GetTeleportSetting("FakeLoadTime")
-
-local function onDescendantAdded(desc)
- if desc:IsA("BasePart") and not desc:IsA("Terrain") then
- if not CollectionService:HasTag(desc, "AxisPart") and desc.Name ~= "__negatepart" then
- desc.LocalTransparencyModifier = 1
- partQueue[#partQueue + 1] = desc
- end
- elseif desc:IsA("Decal") then
- desc.LocalTransparencyModifier = 1
- end
-end
-
-if fakeLoadTime then
- local descendants = workspace:GetDescendants()
-
- for _,desc in pairs(descendants) do
- onDescendantAdded(desc)
- end
-
- partWatch = workspace.DescendantAdded:Connect(onDescendantAdded)
-end
-
----------------------------------------------------------------------
-
local camera = workspace.CurrentCamera
camera.CameraType = "Follow"
camera.CameraSubject = workspace
-messageGui.Visible = true
+gameJoin.Visible = true
local bricks = 0
local connectors = 0
local lastUpdate = 0
-local done = false
+while not game:IsLoaded() do
+ game.Loaded:Wait()
+end
-local function stepBrickConnectorStatus()
- if fakeLoadTime then
- wait(math.random() / 4)
-
- for i = 1, math.random(30, 50) do
- local part = table.remove(partQueue)
-
- if part then
- bricks = bricks + 1
-
- connectors = connectors + #part:GetJoints()
- part.LocalTransparencyModifier = 0
-
- for _,v in pairs(part:GetDescendants()) do
- if v:IsA("Decal") then
- v.LocalTransparencyModifier = 0
- end
- end
- end
- end
-
- done = (#partQueue == 0)
- else
- wait()
- done = game:IsLoaded()
+if not player.Character then
+ camera.CameraSubject = nil
+ message.Text = "Requesting character..."
+
+ local requestCharacter = ReplicatedStorage:WaitForChild("RequestCharacter")
+ requestCharacter:FireServer()
+
+ message.Text = "Waiting for character..."
+
+ while not player.Character do
+ player.CharacterAdded:Wait()
end
end
-while not done do
- stepBrickConnectorStatus()
- message.Text = messageFormat:format(bricks, connectors)
+if not exitOverride.Visible then
+ gameJoin.Visible = false
end
-if partWatch then
- partWatch:Disconnect()
- partWatch = nil
-end
+camera.CameraType = "Custom"
+camera.CameraSubject = player.Character
-camera.CameraSubject = nil
-message.Text = "Requesting character..."
-
-wait(1)
-
-local rep = game:GetService("ReplicatedStorage")
-local requestCharacter = rep:WaitForChild("RequestCharacter")
-
-requestCharacter:FireServer()
-message.Text = "Waiting for character..."
-
-while not player.Character do
- player.CharacterAdded:Wait()
- wait()
-end
-
-messageGui.Visible = false
-camera.CameraType = "Custom"
\ No newline at end of file
+script:Destroy()
\ No newline at end of file
diff --git a/shared.project.json b/shared.project.json
index 94a365b..49da71c 100644
--- a/shared.project.json
+++ b/shared.project.json
@@ -1,50 +1,45 @@
{
- "name": "MainModule",
+ "name": "SNZ_SHARED",
"tree":
{
- "$path": "shared.lua",
-
- "ReplicatedStorage":
+ "$className": "Folder",
+
+ "MainModule":
{
- "$className": "Folder",
-
- "ItemData": { "$path": "Shared/ItemData" },
- "AssetUtil": { "$path": "Shared/AssetUtil.lua" },
- "BrickColors": { "$path": "Shared/BrickColors.lua" },
- "PlaceData": { "$path": "Shared/PlaceData.lua" },
+ "$path": "shared.lua",
- "SharedScripts":
+ "ReplicatedStorage":
{
"$className": "Folder",
- "Sky": {"$path": "Client/Sky"},
- "Moon": {"$path": "Client/Moon"},
- "SunRays": {"$path": "Client/SunRays"},
+ "ItemData": { "$path": "Shared/ItemData" },
+ "AssetUtil": { "$path": "Shared/AssetUtil.lua" },
+ "BrickColors": { "$path": "Shared/BrickColors.lua" },
+ "PlaceData": { "$path": "Shared/PlaceData.lua" },
- "Mouse": {"$path": "UI/Mouse/Mouse.client.lua" },
- "FpsCap": {"$path": "Client/FpsCap.client.lua" },
- "LensFlare": {"$path": "Client/LensFlare.client.lua"}
- }
- },
-
- "ServerScriptService":
- {
- "$className": "Folder",
-
- "LightingConfig":
+ "SharedScripts":
+ {
+ "$className": "Folder",
+
+ "Sky": {"$path": "Client/Sky"},
+ "Moon": {"$path": "Client/Moon"},
+ "SunRays": {"$path": "Client/SunRays"},
+
+ "Mouse": {"$path": "UI/Mouse/Mouse.client.lua" },
+ "FpsCap": {"$path": "Client/FpsCap.client.lua" },
+ "LensFlare": {"$path": "Client/LensFlare.client.lua"}
+ }
+ },
+
+ "ServerStorage":
{
- "$path": "Server/Scripts/LightingConfig.server.lua"
- }
- },
-
- "ServerStorage":
- {
- "$className": "Folder",
-
- "PlayerDataStore":
- {
- "$path": "Server/Resources/PlayerDataStore.lua"
+ "$className": "Folder",
+
+ "PlayerDataStore":
+ {
+ "$path": "Server/Resources/PlayerDataStore.lua"
+ }
}
}
}