From 5fd0da89a94678932b2717a12aa1975b0aa0fb3a Mon Sep 17 00:00:00 2001 From: CloneTrooper1019 Date: Sun, 10 Nov 2019 00:39:43 -0600 Subject: [PATCH] First stable release! --- .gitignore | 2 - .vscode/tasks.json | 14 +- Bin/.gitignore | 350 +++++++++++++++ Bin/BevelConverter/App.config | 6 + Bin/BevelConverter/BevelConverter.csproj | 90 ++++ Bin/BevelConverter/BevelConverter.sln | 22 + Bin/BevelConverter/Extensions/Formatting.cs | 94 ++++ .../Extensions/RegistryHelper.cs | 17 + Bin/BevelConverter/Geometry/Mesh.cs | 410 ++++++++++++++++++ Bin/BevelConverter/Geometry/Vertex.cs | 15 + Bin/BevelConverter/Program.cs | 288 ++++++++++++ Bin/BevelConverter/Properties/AssemblyInfo.cs | 36 ++ .../Properties/Resources.Designer.cs | 83 ++++ Bin/BevelConverter/Properties/Resources.resx | 127 ++++++ Bin/BevelConverter/Resources/BevelPart.rbxm | Bin 0 -> 4568 bytes Bin/BevelConverter/Resources/Bevels.mesh | Bin 0 -> 3353 bytes Client/Camera/Popper.lua | 3 +- Client/Explosions/init.client.lua | 4 +- Client/ForceFields.client.lua | 28 +- Client/FpsCap.client.lua | 29 +- Client/HumanoidLabels/init.client.lua | 31 +- Client/InputGateway.client.lua | 185 -------- Client/LensFlare.client.lua | 62 +-- Client/Music.client.lua | 3 +- Client/Sky/Star.rbxmx | 2 +- Client/Sky/init.client.lua | 46 +- Client/SunRays/init.client.lua | 1 + .../Resources/InputGateway/Client.client.lua | 37 +- .../Resources/InputGateway/Server.server.lua | 14 +- Server/Scripts/LightingConfig.server.lua | 25 -- Server/Scripts/LoadTools.server.lua | 2 +- Server/Scripts/Time.server.lua | 2 +- Shared/PlaceData.lua | 10 +- UI/ConsoleTweaks.client.lua | 12 +- UI/Messages/Message.rbxmx | 6 +- UI/Messages/Player.rbxmx | 10 +- UI/Mouse/ClickToMove.client.lua | 13 +- UI/SafeChat/AspectRatio.model.json | 9 + UI/SafeChat/ChatButton.model.json | 44 ++ UI/SafeChat/Click.model.json | 8 - UI/SafeChat/Hint.model.json | 15 - UI/SafeChat/SafeChat.client.lua | 62 +-- UI/SafeChat/init.meta.json | 11 +- UI/Topbar/Config.lua | 56 +++ UI/Topbar/Topbar.client.lua | 219 +++++++--- UI/Topbar/init.meta.json | 2 +- UploadGame.ps1 | 18 + core.project.json | 82 ++-- default.project.json | 4 +- join.client.lua | 113 ++--- shared.project.json | 67 ++- 51 files changed, 2141 insertions(+), 648 deletions(-) delete mode 100644 .gitignore create mode 100644 Bin/.gitignore create mode 100644 Bin/BevelConverter/App.config create mode 100644 Bin/BevelConverter/BevelConverter.csproj create mode 100644 Bin/BevelConverter/BevelConverter.sln create mode 100644 Bin/BevelConverter/Extensions/Formatting.cs create mode 100644 Bin/BevelConverter/Extensions/RegistryHelper.cs create mode 100644 Bin/BevelConverter/Geometry/Mesh.cs create mode 100644 Bin/BevelConverter/Geometry/Vertex.cs create mode 100644 Bin/BevelConverter/Program.cs create mode 100644 Bin/BevelConverter/Properties/AssemblyInfo.cs create mode 100644 Bin/BevelConverter/Properties/Resources.Designer.cs create mode 100644 Bin/BevelConverter/Properties/Resources.resx create mode 100644 Bin/BevelConverter/Resources/BevelPart.rbxm create mode 100644 Bin/BevelConverter/Resources/Bevels.mesh delete mode 100644 Client/InputGateway.client.lua delete mode 100644 Server/Scripts/LightingConfig.server.lua create mode 100644 UI/SafeChat/AspectRatio.model.json create mode 100644 UI/SafeChat/ChatButton.model.json delete mode 100644 UI/SafeChat/Click.model.json delete mode 100644 UI/SafeChat/Hint.model.json create mode 100644 UI/Topbar/Config.lua create mode 100644 UploadGame.ps1 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 0000000000000000000000000000000000000000..6129f5008ee192ed9dbeed7dbe6c061822ebd2cb GIT binary patch literal 4568 zcmb7IOOG2x5FQ(okU(Hbcx55r1@3Ib0S*yj*ZYvsu4CC&I5*?=dX(8|Yo<-s9Dpkl z5*#^$_yhbFF8l-}4t?YX^_Ao4>6x}YDXHiAb#-;UXC9>Lt5{v_{qWzdo4YrI;JIKq z=)`n>JUaN0uHJuoZ|*ec>Nbtzt63a{kv^Df^@WNOowewxPUmts91Y&3>vw2?%q<)- z@6UTb{`FJvN9*tJZ~XGlzlY!AdABzly-nx4xFIqmMG(9|<6LIbzDPAs#X~^fr1R^z zAu`v%6w4N2%_^+<6!xWz$185F{@`K%HF|-~fDHD|3m+umRHbs<41j@PSQTU-R{#kQ zMfjLj6_*Ds+D4-W@DM=exJ&1^Xn@QO9ABgXj>CC65us#}!16tMeh&a5^D>S*Gz!RW zGMnohUe)7EfGe%lWl7krP%AF%2$4Ysk_Is7l51JuJ$eJ7K?bt2dL67Qa@A3;(WK4^ zX;$vQZaG08Z_piV1~Sj%2wQYS(ou07jb)P!u@05#;Z%&(lO@WpTV|9+DmhKneAXSa zQ~0e5RS;aIAJ57CKi&Q9*WUqj!v!+J)}46iQ0&E~f-Bg5ZvFFm+Ai)Ii$TJl_US$M-);Jeg7RxMKW(_w_ zfeWWJp=C-sqBR<<7o@T~cuQoE$#^kjzU~pP4drbBjdM^nO2Mv2Vbnm1Ih0?^7-|R=QOP8_I1*ZL2FC=yvX>JwAagPN$bp>1GSngoC2tZuk=Nj(AcH&=z-tCF z8O!v9VmXfV0=D3gUc)xJn3f%A8`64^KR^cHS$3f|$x#iEBGmPvHLR7={WMZ3?JUnL z{#Y6){Yb`&>g%EsOYj#CIyxIpkJ@;g)hkqhR->*v16Z$D0P-1n1;A_e3LdBx*UdtJ*6kI5MYz}Q6)>TGuK;wZ zSKtKf_6ioYsaF6Bx~iQ0&E|#yc)}Tq4FF8T3TxBZ zrb0kB_X=)G0KQh`uK=yE{%sZNc`mD)48Rg*D#j=;Hx=mtL-J%F}b-jl5 z_6nKnU_*ucfP~qj0W!BSBd?IKFWMl|Z_rcR6=hJgTj4N;E9RC;SjJh^`Q6?YxLk2= zB?QCzl@MqIs#6J3v#_J8^KYz#{>(j5>E($CwMqx#31nUq2KW}sreemQu8gS~cx`1x z#6bU`&(YAdg8k0^&h_ADeuM)y)PUE@k4|@EoWA*X>3H_OA1SV)T aVDlw48;#@M5nuC91iE_g(ei)JXa55LckuTB literal 0 HcmV?d00001 diff --git a/Bin/BevelConverter/Resources/Bevels.mesh b/Bin/BevelConverter/Resources/Bevels.mesh new file mode 100644 index 0000000000000000000000000000000000000000..eaea9510d4b817dde739e30cddd432250f4cef61 GIT binary patch literal 3353 zcma);J989A6onf}HnJoP_ysbyc?!$sVF_VN_@UvE5m982Kmb*c*j3;na@CFr2%PW( z9P2+2?UXYjQi%8i4jhoE%Bmfoujlqoch8QCDV@4!XTLr7c28@iM|U4Qy#LG3N7l}+ ztjz6m%L_AZ+Ff?eZAjOjy&g)NvV~+`zWB=hNw3Z~)8O0WIJI%eH)+*da%=F2(O5p#N4mTQH>*JF7;Ih6UFX344i+=|{s8{%X3*1n*%6MOnx$U0YgQecl*)$#hb6zhJ(Rq zWZ#p4Q*F5$Po5VOIAdFmygPqCEwVhgPF}_p&1}wQD+^`}^Nkdk&)2M>;lg|o7xH`# z=PKmUH{zJhvw2<*SN%HtbI#Z*%;(zqLf?c7^F|gdg=*#mOb78)SV-0@3m<#7G z;yeQzb7B7?jyx|tk3WnpdgkkJ|1)2a=dmwQ-!NaoO_ASn$UOC9=@aRIbkIC?(S-lhJoS(X|CxE}=h7F_Vd;o@>QU*KbX;Oqgg;@P%B%># zWWt{`PyNz_XC{PSHcw?Hg#XHfrysAW%)&iBOAkDi_r8`+NvBQtGtyb<8)?OaUzN^D qYtnfW{#)rgX 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" + } } } }