the cutting room mirror

Superliminal

This article has a talk page!
view on tcrf.net

This page contains notes for the game Superliminal.

Version List#

Pre-Release Prototypes#

All of these prototypes (Excluding "Museum of Simulation Technology Version 1") are not downloadable at this time.

Build Number

Release Date

Notes

Source

Museum of Simulation Technology

Version 1

10/27/2013

Playable Tech Demo that was the precursor to Superliminal.

Source

???

3/14/2014?

Preview trailer for Game Developers Conference 2014.

Source

???

8/12/2014?

Summer Promo Trailer

Source

???

9/15/2015?

Work in Progress Update #001 & played by Polygon.

Pillow Castle Trailer 9/15/2015
Polygon 10/26/2015

???

6/18/2016?

"Pre-Alpha Prototype" played by Gamespot at E3 2016.

Source

Unannounced Game Title

DEMO_4219134PAX

4/2/2019

Demo was played by Giant Bomb and it seems it may have been used for a Penny Arcade Expo, but none of the 2019 dates match up with the build date.

Source

Superliminal

???

6/19/2019?

E3 2019 Trailer

Source

???

8/29/2019?

Instructional Trailer

Source

???

9/6/2019?

TheBrainJ's PAX West 2019 Dev Interview

Source

???

11/7/2019?

Launch Trailer

Source

Epic Games Versions#

For the first year after release, Superliminal was an Epic Games exclusive. Unlike Steam and GOG, no database exists for the Epic Games builds of Superliminal, so there's limited information for versions beyond once it stopped being an exclusive. The data in this table comes mostly from the speedrunning community, and a version's absence does not necessarily mean that it did not exist.

Release Date (UTC)

Windows Version Number

MacOS Version Number

Notes

2019-11-12 15:00:00

1.0.2019.11.11.963

No MacOS build

2019-11-13 ~01:54:00

1.0.2019.11.12.1005

No MacOS build

Twitter

2019-11-15 ~22:40:00

1.0.2019.11.15.707

No MacOS build

Twitter

2019-11-20 ~21:39:00

1.0.2019.11.19.1061

No MacOS build

Twitter

?

1.05.2019.12.6.1064

No MacOS build

This video is the only known evidence of this version's existence

2019-12-10 ~01:34:00

1.05.2019.12.9.797

No MacOS build

Twitter

?

1.05.2019.12.13.185

No MacOS build

2020-7-7 ~19:00:00

1.10.2020.7.6.877

No MacOS build

Mailing list (broken)

~2020-11-5

1.10.2020.11.4.1133

?

~2020-11-12

1.10.2020.11.11.1419

?

2020-11-25 ~05:27:00

1.10.2020.11.24.1126

?

Twitter

~2020-12-11

1.10.2020.12.10.?

?

~2021-4-23

1.10.2021.4.19.?

?

~2021-5-19

1.10.2021.5.10.?

?

2021-11-17 ~21:31:00

1.10.2021.11.12.858.39

?

~2021-11-24

1.10.2021.11.12.858.39

?

~2021-12-21

1.10.2021.12.20.828.57

?

~2022-2-21

1.10.2022.2.20.838.2

?

~2022-12-22

1.10.2022.12.19.1005.12

?

~2023-2-19

1.10.2023.2.17.882.59

?

Steam Versions#

App ID: 1049410

Release Date (UTC)

Steam Build ID

Windows

MacOS

Version Number

Steam Manifest ID

Version Number

Steam Manifest ID

Version Number

Steam Manifest ID

2020-10-20 19:49:33

5711630

None

189814675170018135

None

4694135706383365108

2020-10-25 07:41:42

5731400

1.10.2020.10.24.58

5361343928601884083

1.10.2020.10.24.65

8610532725808758001

2020-10-30 03:19:54

5758952

1.10.2020.10.28.32

950493532859608225

1.10.2020.10.28.45

5847434069998482031

2020-10-30 04:40:41

5759192

1.10.2020.10.29.1225

1314310522287257155

1.10.2020.10.29.1241

7261873955311947198

2020-10-30 19:51:48

5763344

None

189814675170018135

None

4694135706383365108

2020-11-04 10:07:16

5781635

1.10.2020.11.3.1313

7959148786794348749

1.10.2020.11.3.1329

2907352730406142537

2020-11-04 18:16:48

5783691

1.10.2020.11.4.465

2101740051927655154

No MacOS build

2020-11-04 23:57:19

5784879

1.10.2020.11.4.884

947562870178145618

No MacOS build

2020-11-05 02:11:47

5785443

1.10.2020.11.4.1036

2358911993831512816

No MacOS build

2020-11-05 03:22:22

5785674

No Windows build

1.10.2020.11.4.1149

8931970647707267887

2020-11-05 04:36:26

5785867

No Windows build

No MacOS build

2020-11-12 19:59:39

5819802

1.10.2020.11.11.1354

6216358686798469830

1.10.2020.11.11.1376

5535863258957001037

2020-11-23 23:46:17

5862410

1.10.2020.11.20.951

3384338906330942294

1.10.2020.11.20.999

5570690285424782069

2020-12-04 18:09:40

5920757

1.10.2020.12.3.1217

3366845502878191273

1.10.2020.12.3.1261

2770654230370314229

2020-12-04 19:43:24

5924422

No Windows build

No MacOS build

2020-12-04 20:40:53

5924654

No Windows build

No MacOS build

2020-12-04 21:28:03

5924843

No Windows build

No MacOS build

2020-12-07 20:51:40

5934468

No Windows build

No MacOS build

2020-12-11 18:45:15

5952707

1.10.2020.12.10.971

7110343821965905499

1.10.2020.12.10.1010

7988569650394646995

2021-04-23 14:58:00

6564234

1.10.2021.4.18.111

119793487193499281

1.10.2021.4.18.131

5835855611506103577

2021-05-19 16:13:26

6678674

1.10.2021.5.10.791

4743178048305939315

1.10.2021.5.10.840

5868874548269431974

2021-11-05 16:52:03

7665136

1.10.2021.11.5.550.43

4269649591510852563

No MacOS build

2021-11-13 00:19:18

7705875

1.10.2021.11.12.858.39

3614934652523843138

No MacOS build

2021-11-14 02:46:21

7709483

1.10.2021.11.12.858.39

3614934652523843138

No MacOS build

2021-11-24 02:14:29

7767071

1.10.2021.11.12.858.39

7224305671286705868

No MacOS build

2021-12-17 22:10:17

7904836

1.10.2021.12.16.1298.39

3785643547020750819

No MacOS build

2021-12-21 01:32:22

7918004

1.10.2021.12.20.828.57

5131471526541586811

No MacOS build

2022-02-11 17:06:23

8188286

No Windows build

1.10.2021.12.20.828.57

5418825235250573680

2022-02-11 17:06:38

8188287

No Windows build

No MacOS build

2022-02-21 08:03:03

8242454

1.10.2022.2.20.838.2

7149275414135219251

1.10.2022.2.20.838.2

7292519601607832715

2022-02-21 15:25:34

8245107

1.10.2022.2.20.838.2

7871867229536493116

1.10.2022.2.20.838.2

4275929868529713746

2022-12-22 05:48:50

10182655

1.10.2022.12.19.1005.12

4972230278923180684

1.10.2022.12.19.1005.12

3613197538817921033

2023-01-14 04:54:03

10321016

No Windows build

No MacOS build

2023-02-19 05:24:58

10585644

1.10.2023.2.17.882.59

3646111955971398231

1.10.2023.2.17.882.59

6596648641613544432

2023-02-28 19:09:40

10651429

No Windows build

1.10.2023.2.17.882.59

3891342746257394329

(Source: SteamDB)

GOG Versions#

Product ID: 1766270223

Release Date (UTC)

GOG Version

Windows

MacOS

Version Number

GOG Build ID

Version Number

GOG Build ID

Version Number

GOG Build ID

2020-11-05

1.05

?

53840016944444904

No MacOS build

2020-11-05

1.05a

No Windows build

?

53840517421226756

2020-11-18

1.06

?

53861814159751987

?

53861789537696362

2020-12-14

1.11

?

53943933947580428

?

53943880984872122

2020-12-15

1.11b

No Windows build

1.10.2020.12.10.1023

53956329921041056

2021-04-26 (Linux) / 2021-04-29 (Windows and Mac)

1.15

?

54319575114761644

1.10.2021.4.19.340

54319550567550158

2021-05-21

1.16

1.10.2021.5.10.811

54381450504747385

1.10.2021.5.10.855

54406567169445986

2021-11-17 ~21:31:00

1.2

?

54932849289074337

No MacOS build

2021-11-25

1.2a

1.10.2021.11.12.858.39

54955539001667562

No MacOS build

2021-12-21

1.22

1.10.2021.12.20.828.57

55032537984174133

No MacOS build

2022-02-21 18:00:00

1.3

1.10.2022.2.20.838.2

55212321996740286

1.10.2022.2.20.838.2

55212349688070046

2022-12-22

1.3_c

1.10.2022.12.19.1005.12

56087087798986391

1.10.2022.12.19.1005.12

56087075605946159

2023-02-19

1.4

1.10.2023.2.17.882.59

56263459448436749

1.10.2023.2.17.882.59

56263469054281749

(Source: GOG Database)

Console and Mobile Versions#

  • Tracking the console version history is difficult, especially for Xbox, so it's likely that this list is missing some versions and contains some inaccuracies.
  • "Xbox App" refers to the PC version of the game which is bought through the Microsoft Store or the Xbox app; even though it's on PC, it is much more reminiscent of the console versions than the other PC versions (it has the altered main menu, different physics, and a similar update history), which is why it's here.
  • The Playstation versions seem to have two build numbers for each release, likely for US and EU.
  • Based on video evidence, there seems to have been game versions for both the Xbox One and Xbox App which were available at the same point in time, such as versions 1.10.10.14.1412 and 1.10.12.6.741, as well as versions 1.0.12.7.971 and 1.0.4.14.705. It's currently unclear why this was the case, as unlike with Playstation there is nothing indicating that these were regional differences.

Build Number

Release Date

Platform

PC Equivalent

Notes

1.10.5.4.989

7/7/2020

Switch

1.10.2020.7.6.877

Video

1.10.5.21.1214

7/7/2020

Xbox One

1.10.2020.7.6.877

Video

1.10.6.12.1370 / 1.10.6.12.1438

7/7/2020

PS4

1.10.2020.7.6.877

Video / Video

1.10.10.13.1154 / ???

10/13/2020

PS4

1.10.2020.7.6.877

Changed the Superluminal achievement requirement to 35 minutes. Video / 01.02

1.10.10.22.188 / 1.10.10.22.950

10/22/2020

PS4

1.10.2020.7.6.877

Video / Video

1.10.8.20.1319

9/16/2021

Xbox One

1.10.2021.5.10.791

Video

.6.8.25.1006

9/16/2021

Xbox App

1.10.2021.5.10.791

Video

1.10.10.6.910

10/7/2021

Xbox One

1.10.2021.5.10.791

Likely changed the Superluminal achievement requirement to 35 minutes and fixed speedrun timer issues. Video

1.0.2.0

10/7/2021

Xbox App

1.10.2021.5.10.791

Likely fixed speedrun timer issues. Video

1.10.10.14.1412

10/14/2021?

Xbox One

1.10.2021.5.10.791

Video

1.10.11.18.281 / ???

11/18/2021

PS4

1.10.2021.5.10.791

Video

1.10.12.6.741

12/6/2021?

Xbox One

1.10.2021.5.10.791

Latest release. Video

1.10.12.10.834 / ???

12/10/2021

PS4

1.10.2021.5.10.791

Fixed restart from checkpoint option. Video

1.10.12.20.782 / 1.10.12.20.824

12/20/2021

PS4

1.10.2021.5.10.791

Fixed Platinum Trophy issues. Video

1.1

12/23/2021

Switch

1.10.2021.5.10.791

Latest release. Video

1.10.1.21.1115 / 1.10.1.23.590

1/22/2022

PS4

1.10.2021.5.10.791

Latest release. Fixed a bug with the speedrun timer in Retrospect. Video / Video

1.0.12.7.971

???

Xbox App

1.10.2021.5.10.791

Video

1.0.4.14.705

???

Xbox App

1.10.2021.5.10.791

Video

1.10.11.4.765

11/21/2022

Xbox Series X/S

1.10.2021.5.10.791

Latest release. Video

1.10.11.11.667

11/21/2022

PS5

1.10.2021.5.10.791

Latest release. The gameplay warning doesn't display when pressing new game, but everything else indicates 2021.5.10. Video

1.0.11.30.757

???

Xbox App

1.10.2021.5.10.791

Latest release. The gameplay warning doesn't display when pressing new game, but everything else indicates 2021.5.10.

1.13

7/30/2024

iOS

1.10.2021.5.10.791

Seems like this might've only been available to people who got the game early because of their timezone.

1.13

7/30/2024

Android

1.10.2021.5.10.791

1.13.2

7/30/2024

iOS

1.10.2021.5.10.791

1.14

8/1/2024

Android

1.10.2021.5.10.791

Fixed the fire extinguisher, fire alarm and chess piece rewards being available from the start.

1.14

8/7/2024

iOS

1.10.2021.5.10.791

1.15

8/26/2024

Android

1.10.2021.5.10.791

Added level select.

1.15

8/30/2024

iOS

1.10.2021.5.10.791

Added level select.

1.16

9/18/2024

Android

1.10.2021.5.10.791

1.16

9/25/2024

iOS

1.10.2021.5.10.791

Latest release.

1.22

4/1/2026

Android

1.10.2021.5.10.791

Latest release.

Steam Demos#

App ID: 1271490
(I don't think it's possible to download this from steam, even if someone had a license for it. Only way I think it could be found is if someone downloaded it while the demo was available and decided to save it to a backup drive).
{| class="wikitable" ! Build Number ! Release Date ! Steam Build ID ! Steam Manifest ID ! Notes |- | 1.10.2020.3.17.067 || 3/18/2020 || 4789330 || 512083530367008877 || Currently lost (according to SteamDB, it's unknown what files it started with). Video |- | 1.10.2020.3.19.1077 || 3/20/2020 || 4799269 || 1355647673322366196 || Video |- | 1.10.2020.6.1.1032 || 6/15/2020 || 5107356 || 8754035545394644518 || Video |}

Debug Commands Decompiling#

DrawCursorScriptHand#

Commands mentioned: pm

using UnityEngine;
using UnityEngine.UI;

public class DrawCursorScriptHand : MonoBehaviour
{
  public Texture pointTexture;
  private Texture resetPointTexture;
  public Texture handTexture;
  public Texture grabTexture;
  public Texture blockedTexture;
  public Texture returnTexture;
  public Texture pointLeftAndRightTexture;
  public Texture pointUpAndDownTexture;
  public Texture changePointTexture;
  public RawImage GrabProgress;
  public string PowerupHoverProgressSound;
  public float PowerupHoverProgressSoundTimerBase;
  public float PowerupHoverProgressSoundTimer;
  public RawImage BeingTargeted;
  public Texture optionalCanGrabUITexture;
  public Texture interactTexture;
  public Texture instantProjectTexture;
  private bool drawInteractTexture;
  private bool drawMPGroupTriggerStatus;
  private float? interactCountdownProgress;
  private bool drawButtonPrompt_Consoles;
  private int lastUpdatedFrame;
  private bool hasDrawnScreenYet;
  private bool drawGrabTexture;
  public bool drawPointLeftAndRightTexture;
  public bool drawPointUpAndDownTexture;
  public Texture interact_SWITCH_Texture;
  public Texture interact_PS4_Texture;
  public Texture interact_XBOX_Texture;
  public RawImage ButtonPrompt_Consoles;
  public ResizeScript resizescript;
  public Text MultiplayerGroupTriggerStatus;
  private int point_texture_size = 20;
  private int hand_texture_size = 80;
  private int grab_texture_size = 80;
  private int blocked_texture_size = 80;
  public float xOffset;
  public float yOffset;
  public float xMoveSpeed;
  public float yMoveSpeed;
  public bool driftingCrosshair;
  public bool growCursor;
  public float growSpeed;
  public float placeholder;
  public bool ForceHideCursor;
  private Canvas canvas;
  private RawImage cursor;
  public Vector2 crosshairScreenPos;
  private KeystrokeTracker typedPM;
  private Material grabProgressMaterial;
  private MultiplayerType matchType;
  private float debugHideCursorTimer;
  private const float DebugHideCursorTime = 1f;
  private bool debugHideCursor;
  private int lastPlayerCount = -1;
  private int lastTotalPlayerCount = -1;

  private void Start()
  {
    this.matchType = MultiplayerHelper.GetMatchType();
    this.resetPointTexture = this.pointTexture;
    if ((Object) this.canvas == (Object) null)
    {
      this.canvas = this.transform.GetComponentInChildren<Canvas>();
      this.cursor = this.canvas.GetComponentInChildren<RawImage>();
    }
    this.cursor.gameObject.SetActive(false);
    this.typedPM = new KeystrokeTracker()
    {
      KeyCodes = new KeyCode[2]{ KeyCode.P, KeyCode.M }
    };
  }

  private void OnDestroy()
  {
    Object.Destroy((Object) this.grabProgressMaterial);
    this.grabProgressMaterial = (Material) null;
  }

  private void Update()
  {
    if ((Object) this.canvas == (Object) null)
      return;
    if (!GameManager.GM.PM.canControl || this.ForceHideCursor || this.debugHideCursor)
    {
      this.cursor.gameObject.SetActive(false);
    }
    else
    {
      if (!this.cursor.gameObject.activeSelf)
        this.cursor.gameObject.SetActive(true);
      if (this.drawInteractTexture)
      {
        this.DrawCenteredGUI(this.interactTexture, this.hand_texture_size);
        this.hasDrawnScreenYet = false;
      }
      else if (!this.resizescript.isReadyToGrab && !this.resizescript.isGrabbing && (!this.resizescript.isObjectBlocked && !this.drawGrabTexture))
      {
        if (!this.drawPointUpAndDownTexture && !this.drawPointLeftAndRightTexture)
          this.DrawCenteredGUI(this.pointTexture, this.point_texture_size);
        else if (this.drawPointUpAndDownTexture)
          this.DrawCenteredGUI(this.pointUpAndDownTexture, this.grab_texture_size);
        else if (this.drawPointLeftAndRightTexture)
          this.DrawCenteredGUI(this.pointLeftAndRightTexture, this.grab_texture_size);
      }
      else if (this.resizescript.isGrabbing || this.drawGrabTexture || this.drawPointUpAndDownTexture)
      {
        if (this.resizescript.isObjectBlocked)
        {
          this.DrawCenteredGUI(this.blockedTexture, this.blocked_texture_size);
        }
        else
        {
          this.drawGrabTexture = true;
          if (this.drawGrabTexture)
            this.DrawCenteredGUI(this.grabTexture, this.grab_texture_size);
          else if (this.drawPointUpAndDownTexture)
            this.DrawCenteredGUI(this.pointUpAndDownTexture, this.grab_texture_size);
        }
      }
      else if (!this.resizescript.isGrabbing && !this.resizescript.isObjectBlocked && this.resizescript.isObjectReadyToReturn)
        this.DrawCenteredGUI(this.returnTexture, this.hand_texture_size);
      else if (!this.resizescript.isGrabbing && !this.resizescript.isObjectBlocked)
      {
        if (!this.resizescript.isPointingAtInstantProjectObj)
        {
          this.DrawCenteredGUI(this.handTexture, this.hand_texture_size);
          if ((bool) (Object) this.optionalCanGrabUITexture)
            this.DrawCenteredGUI(this.optionalCanGrabUITexture, this.hand_texture_size);
          this.drawButtonPrompt_Consoles = this.resizescript.GetGrabbedObject_ButtonPromptBool();
        }
        else
          this.DrawCenteredGUI(this.instantProjectTexture, this.hand_texture_size);
      }
      else if (!this.resizescript.isGrabbing && this.resizescript.isObjectBlocked)
        this.DrawCenteredGUI(this.blockedTexture, this.blocked_texture_size);
      if (GameManager.GM.CanUseKeyboardHotKeys() && this.typedPM.Check())
      {
        this.debugHideCursor = !this.debugHideCursor;
        Debug.developerConsoleVisible = !Debug.developerConsoleVisible;
        SaveAndCheckpointManager objectOfType = Object.FindObjectOfType<SaveAndCheckpointManager>();
        objectOfType.showSaveIconWhileSaving = !objectOfType.showSaveIconWhileSaving;
      }
      if (this.driftingCrosshair)
      {
        this.xOffset += Time.deltaTime * this.xMoveSpeed;
        this.yOffset += Time.deltaTime * this.yMoveSpeed;
      }
      if (this.growCursor)
      {
        this.placeholder += Time.deltaTime * this.growSpeed;
        this.point_texture_size = (int) this.placeholder;
      }
      float? percentWaitingToGrab = this.resizescript.GetPercentWaitingToGrab();
      float? forceLetGoProgress = this.resizescript.GetForceLetGoProgress();
      float? recoveryProgress = this.resizescript.GetShouldShowGrabRecoveryProgress();
      bool flag = this.interactCountdownProgress.HasValue && !this.resizescript.isGrabbing;
      this.GrabProgress.gameObject.SetActive(((percentWaitingToGrab.HasValue || forceLetGoProgress.HasValue ? 1 : (recoveryProgress.HasValue ? 1 : 0)) | (flag ? 1 : 0)) != 0);
      if (this.GrabProgress.gameObject.activeSelf && !(bool) (Object) this.grabProgressMaterial)
      {
        this.grabProgressMaterial = new Material(this.GrabProgress.material);
        this.GrabProgress.material = this.grabProgressMaterial;
      }
      if (recoveryProgress.HasValue)
      {
        this.grabProgressMaterial.SetFloat("_Progress", 0.0f);
        this.grabProgressMaterial.SetFloat("_Fill", recoveryProgress.Value);
        this.grabProgressMaterial.SetColor("_Tint", Color.white);
      }
      else if (percentWaitingToGrab.HasValue)
      {
        this.grabProgressMaterial.SetFloat("_Progress", percentWaitingToGrab.Value);
        this.grabProgressMaterial.SetFloat("_Fill", 1f);
        this.grabProgressMaterial.SetColor("_Tint", Color.white);
      }
      else if (forceLetGoProgress.HasValue)
      {
        this.grabProgressMaterial.SetFloat("_Progress", forceLetGoProgress.Value);
        this.grabProgressMaterial.SetFloat("_Fill", 0.0f);
        this.grabProgressMaterial.SetColor("_Tint", Color.white);
      }
      else if (flag)
      {
        this.grabProgressMaterial.SetFloat("_Progress", 1f - this.interactCountdownProgress.Value);
        this.grabProgressMaterial.SetFloat("_Fill", 1f);
        this.grabProgressMaterial.SetColor("_Tint", new Color(0.5f, 1f, 0.5f));
      }
      else
        this.PowerupHoverProgressSoundTimer = 0.0f;
      if ((bool) (Object) this.BeingTargeted && this.matchType == MultiplayerType.BattleRoyale)
      {
        MultiplayerPlayer component = GameManager.GM.player.GetComponent<MultiplayerPlayer>();
        if ((bool) (Object) component)
        {
          float? nullable = component.AmIBeingTargeted();
          this.BeingTargeted.gameObject.SetActive(nullable.HasValue);
          if (nullable.HasValue)
            this.BeingTargeted.color = new Color(1f, 0.0f, 0.0f, Mathf.Clamp01(nullable.Value));
        }
      }
      if ((bool) (Object) this.MultiplayerGroupTriggerStatus)
        this.MultiplayerGroupTriggerStatus.gameObject.SetActive(this.drawMPGroupTriggerStatus);
      this.drawInteractTexture = false;
      this.interactCountdownProgress = new float?();
      this.drawGrabTexture = false;
      this.drawButtonPrompt_Consoles = false;
      this.drawMPGroupTriggerStatus = false;
    }
  }

  private void DrawCenteredGUI(Texture texture, int textureSize)
  {
    this.cursor.texture = texture;
    RectTransform component = this.cursor.GetComponent<RectTransform>();
    component.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, (float) textureSize);
    component.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, (float) textureSize);
    this.crosshairScreenPos = new Vector2((float) ((double) Screen.width / 2.0 - (double) textureSize / 2.0) + this.xOffset, (float) ((double) Screen.height / 2.0 - (double) textureSize / 2.0) + this.yOffset);
  }

  private void UpdateMultiplayerGroupTriggerStatus(int playerCount, int totalPlayerCount)
  {
    if (playerCount == this.lastPlayerCount && totalPlayerCount == this.lastTotalPlayerCount)
      return;
    this.lastPlayerCount = playerCount;
    this.lastTotalPlayerCount = totalPlayerCount;
    this.MultiplayerGroupTriggerStatus.text = string.Format("{0} / {1}", (object) this.lastPlayerCount, (object) this.lastTotalPlayerCount);
  }

  public void DrawMultiplayerGroupTriggerStatus(int playerCount, int totalPlayerCount)
  {
    this.UpdateMultiplayerGroupTriggerStatus(playerCount, totalPlayerCount);
    this.drawMPGroupTriggerStatus = true;
  }

  public void DrawInteractGUI(bool includeButtonPrompt, float? countdownProgress = null)
  {
    this.drawInteractTexture = true;
    if (!this.interactCountdownProgress.HasValue)
      this.interactCountdownProgress = countdownProgress;
    if (!includeButtonPrompt)
      return;
    this.drawButtonPrompt_Consoles = true;
  }

  public void DrawGrabGUI() => this.drawGrabTexture = true;

  public void DrawPointLeftAndRightGUI() => this.drawPointLeftAndRightTexture = true;

  public void DrawPointUpAndDownGUI() => this.drawPointUpAndDownTexture = true;

  public void TurnOffPointLeftAndRightAndUpAndDownGUI()
  {
    this.drawPointLeftAndRightTexture = false;
    this.drawPointUpAndDownTexture = false;
  }

  public void ChangePointTexture() => this.pointTexture = this.changePointTexture;

  public void ResetPointTexture() => this.pointTexture = this.resetPointTexture;

  public void ReplacePointTexture(Texture replaceWith) => this.pointTexture = replaceWith;

  public void ReplaceInteractTexture(Texture replaceWith) => this.interactTexture = replaceWith;

  public void ChangePointTextureSize(int textureSize) => this.point_texture_size = textureSize;

  public void StartGrowCursor()
  {
    this.placeholder = (float) this.point_texture_size;
    this.growCursor = true;
  }

  public void SetGrowCursorSpeed(float theSpeed) => this.growSpeed = theSpeed;

  public void ToggleForceCursorOff() => this.ForceHideCursor = true;

  public void ToggleForceCursorOn() => this.ForceHideCursor = false;
}

GifMode#

Commands mentioned: gif

using UnityEngine;
using UnityEngine.Rendering.PostProcessing;

public class GifMode : MonoBehaviour
{
  public PostProcessVolume GifVolume;
  private PostProcessLayer ppLayer;
  private PostProcessLayer.Antialiasing antiAliasingOrig;
  private KeystrokeTracker typedGIF;

  private void Start()
  {
    this.typedGIF = new KeystrokeTracker()
    {
      KeyCodes = new KeyCode[3]
      {
        KeyCode.G,
        KeyCode.I,
        KeyCode.F
      }
    };
    this.ppLayer = this.GetComponent<PostProcessLayer>();
    this.antiAliasingOrig = this.ppLayer.antialiasingMode;
  }

  private void Update()
  {
    if (!GameManager.GM.CanUseKeyboardHotKeys() || !this.typedGIF.Check())
      return;
    PostProcessManager.instance.GlobalSettings.GifModeOn = !PostProcessManager.instance.GlobalSettings.GifModeOn;
    this._UpdateGIFMode();
  }

  private void _UpdateGIFMode()
  {
    this.GifVolume.gameObject.SetActive(PostProcessManager.instance.GlobalSettings.GifModeOn);
    this.ppLayer.antialiasingMode = PostProcessManager.instance.GlobalSettings.GifModeOn ? PostProcessLayer.Antialiasing.None : this.antiAliasingOrig;
  }
}

KeystrokeTracker#

Only added here just for reference.

using UnityEngine;

public class KeystrokeTracker
{
  public KeyCode[] KeyCodes;
  private int currentIndex;
  private const float InARowTime = 1f;
  private float triggerTime;

  public bool Check()
  {
    if (GameManager.GM.CanUseKeyboardHotKeys() && this.KeyCodes.Length >= 2)
    {
      this.triggerTime -= Time.deltaTime;
      if (this.currentIndex > 0)
      {
        if ((double) this.triggerTime <= 0.0)
          this._Reset();
        else if (Input.GetKeyDown(this.KeyCodes[this.currentIndex]))
        {
          this._Next();
          if (this.currentIndex >= this.KeyCodes.Length)
          {
            this._Reset();
            return true;
          }
        }
      }
      else if (Input.GetKeyDown(this.KeyCodes[0]))
        this._Next();
    }
    return false;
  }

  private void _Next()
  {
    ++this.currentIndex;
    this.triggerTime = 1f;
  }

  private void _Reset()
  {
    this.currentIndex = 0;
    this.triggerTime = 0.0f;
  }
}

LevelJumpingScript#

Commands mentioned: fps, tex, =, -, 77, [LeftShift]/[RightShift] + 0-9, gg

using FMODUnity;
using System;
using UnityEngine;
using UnityEngine.SceneManagement;

public class LevelJumpingScript : MonoBehaviour
{
  private static GameObject firstInstance;
  public bool skipToSpecificLevel;
  public int specificLevelToSkipTo;
  private static DateTime currentLevelStartTime = DateTime.Now;
  private static DateTime lastTimeSinceMenu = DateTime.Now;
  public bool inDevFastForwardMode;
  public bool doubleTapForFastForward;
  public float doubleTapForFastForwardTimerBase;
  public float doubleTapForFastForwardTimer;
  public bool allowNoClip;
  public bool noClip;
  public GameObject cameraNoClip;
  public GameObject instanceCameraNoClip;
  public bool doubleTapForNoClip;
  public float doubleTapForNoClipTimerBase;
  public float doubleTapForNoClipTimer;
  public GameObject FPSCounter;
  public ShowTextureStreamingSummary TextureStreamingDebug;
  private readonly KeystrokeTracker fpsTracker = new KeystrokeTracker()
  {
    KeyCodes = new KeyCode[3]
    {
      KeyCode.F,
      KeyCode.P,
      KeyCode.S
    }
  };
  private readonly KeystrokeTracker streamingTracker = new KeystrokeTracker()
  {
    KeyCodes = new KeyCode[3]
    {
      KeyCode.T,
      KeyCode.E,
      KeyCode.X
    }
  };
  public bool cursorOn = true;
  public GameObject cursorObject;

  private void Start()
  {
    UnityEngine.Object.DontDestroyOnLoad((UnityEngine.Object) this);
    if ((UnityEngine.Object) LevelJumpingScript.firstInstance != (UnityEngine.Object) null)
      UnityEngine.Object.DestroyImmediate((UnityEngine.Object) this);
    else
      LevelJumpingScript.firstInstance = this.gameObject;
  }

  private void Update()
  {
    if (GameManager.GM.CanUseKeyboardHotKeys())
    {
      if (this.fpsTracker.Check())
        this.FPSCounter.SetActive(!this.FPSCounter.activeSelf);
      if (this.streamingTracker.Check())
        this.TextureStreamingDebug.enabled = !this.TextureStreamingDebug.enabled;
      if (Input.GetKeyDown(KeyCode.Equals))
      {
        int num = (int) RuntimeManager.GetBus("Bus:/").stopAllEvents(FMOD.Studio.STOP_MODE.ALLOWFADEOUT);
        SceneManager.LoadScene((Application.loadedLevel + 1) % Application.levelCount);
      }
      if (Input.GetKeyDown("-"))
      {
        int num = (int) RuntimeManager.GetBus("Bus:/").stopAllEvents(FMOD.Studio.STOP_MODE.ALLOWFADEOUT);
        SceneManager.LoadScene((Application.loadedLevel - 1) % Application.levelCount);
      }
    }
    if (!((UnityEngine.Object) this.GetComponent<GameManager>() != (UnityEngine.Object) null))
      return;
    int num1 = this.GetComponent<GameManager>().debugModeOn ? 1 : 0;
    if (!GameManager.GM.CanUseKeyboardHotKeys())
      return;
    if ((double) this.doubleTapForFastForwardTimer > 0.0)
    {
      this.doubleTapForFastForwardTimer -= Time.unscaledDeltaTime;
      if (Input.GetKeyDown(KeyCode.Alpha7))
        this.ToggleFastForward();
    }
    else
      this.doubleTapForFastForwardTimer = 0.0f;
    if (!this.doubleTapForFastForward)
    {
      if (Input.GetKeyDown(KeyCode.Alpha7))
        this.ToggleFastForward();
    }
    else if (Input.GetKeyDown(KeyCode.Alpha7))
      this.doubleTapForFastForwardTimer = this.doubleTapForFastForwardTimerBase;
    if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
    {
      for (int index = 0; index < 10; ++index)
      {
        if (Input.GetKeyDown((KeyCode) (48 + index)))
          GameManager.GM.GetComponent<SaveAndCheckpointManager>().TeleportToCheckpointIndexDebug(index);
      }
    }
    if (!this.allowNoClip)
      return;
    if (this.doubleTapForNoClip)
    {
      if ((double) this.doubleTapForNoClipTimer > 0.0)
      {
        this.doubleTapForNoClipTimer -= Time.deltaTime;
        if (Input.GetKeyDown(KeyCode.G))
        {
          if (!this.noClip || (UnityEngine.Object) this.instanceCameraNoClip == (UnityEngine.Object) null)
            this.CreateNoClipCamera();
          else
            this.EndNoClip();
        }
      }
      else
        this.doubleTapForNoClipTimer = 0.0f;
    }
    if (!Input.GetKeyDown(KeyCode.G))
      return;
    if (!this.doubleTapForNoClip)
    {
      if (!this.noClip || (UnityEngine.Object) this.instanceCameraNoClip == (UnityEngine.Object) null)
        this.CreateNoClipCamera();
      else
        this.EndNoClip();
    }
    else
      this.doubleTapForNoClipTimer = this.doubleTapForNoClipTimerBase;
  }

  private void CreateNoClipCamera()
  {
    MonoBehaviour.print((object) "noclip");
    this.instanceCameraNoClip = UnityEngine.Object.Instantiate<GameObject>(this.cameraNoClip, GameManager.GM.playerCamera.transform.position, Quaternion.identity);
    this.instanceCameraNoClip.transform.LookAt(this.instanceCameraNoClip.transform.position + Vector3.Scale(GameManager.GM.playerCamera.transform.forward, new Vector3(1f, 0.0f, 1f)), Vector3.up);
    GameManager.GM.player.gameObject.SetActive(false);
    this.noClip = true;
  }

  private void EndNoClip()
  {
    GameManager.GM.player.gameObject.transform.position = this.instanceCameraNoClip.transform.position;
    Vector3 worldPosition = this.instanceCameraNoClip.transform.position + Vector3.Scale(this.instanceCameraNoClip.transform.forward, new Vector3(1f, 0.0f, 1f));
    GameManager.GM.player.transform.LookAt(worldPosition);
    GameManager.GM.player.gameObject.SetActive(true);
    UnityEngine.Object.Destroy((UnityEngine.Object) this.instanceCameraNoClip);
    this.noClip = false;
  }

  private void ToggleFastForward()
  {
    if (!this.inDevFastForwardMode)
    {
      Time.timeScale = 10f;
      this.inDevFastForwardMode = true;
    }
    else
    {
      Time.timeScale = 1f;
      this.inDevFastForwardMode = false;
    }
  }

  private void OnApplicationFocus(bool hasFocus)
  {
  }

  public void GoToNextLevel()
  {
    GameManager.GM.MyLog("next level");
    SceneManager.LoadScene((Application.loadedLevel + 1) % Application.levelCount);
  }
}

MultiplayerLevelInfo#

Commands mentioned: photon

using ExitGames.Client.Photon;
using Photon.Pun;
using Photon.Pun.UtilityScripts;
using Photon.Realtime;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;

public class MultiplayerLevelInfo : MonoBehaviourPunCallbacks
{
  private const string recentlyUsedChunksNameKey = "recentlyUsedChunks";
  public bool IsPlayerCloneable;
  public CountdownTimer CountdownTimer;
  public PlayerProgressTracking PlayerPath;
  public UnityEvent OptionalInitializationEvents;
  public PowerupMetadata PowerupMetadata;
  public MultiplayerLevelChunk[] LevelChunks;
  public int NumberOfLevelChunksToUse = 6;
  public Camera[] ObservationModeCameras;
  public GameObject PhotonStats;
  public UnityEvent OnAllPlayersLoaded;
  [Tooltip("Look under this component for spawn points")]
  public GameObject OptionalSpawnPointSearch;
  public Transform[] TemporarySpawnPointsForAdditive;
  public GlobalPowerupState GlobalPowerupState;
  public MultiplayerLevelProfile LevelProfile;
  [NonSerialized]
  public MultiplayerSpawnPoints[] SpawnPoints;
  private HashSet<string> recentlyUsedChunkNames;
  private KeystrokeTracker trackerStats = new KeystrokeTracker()
  {
    KeyCodes = new KeyCode[6]
    {
      KeyCode.P,
      KeyCode.H,
      KeyCode.O,
      KeyCode.T,
      KeyCode.O,
      KeyCode.N
    }
  };
  public int AmountToSpaceOutChunks = 400;
  private bool sentLightProbesReady;
  [NonSerialized]
  public List<MultiplayerLevelChunk> FinalOrderedChunks;
  private bool countdownTimerFired;
  private Dictionary<string, FixedObjectAlongLevelPath> knownPositions = new Dictionary<string, FixedObjectAlongLevelPath>();
  private HashSet<Player> recentlyStunnedPlayers = new HashSet<Player>();

  private void Awake()
  {
    if (!(bool) (UnityEngine.Object) GameManager.GM)
      return;
    MultiplayerMode component1 = GameManager.GM.GetComponent<MultiplayerMode>();
    if ((bool) (UnityEngine.Object) component1)
      component1.LevelInfo = this;
    MultiplayerLevelInfoAdditive component2;
    if ((component2 = this.GetComponent<MultiplayerLevelInfoAdditive>()) == null)
      return;
    int randomSeed = GameManager.GM.GetComponent<MultiplayerMode>().GetRandomSeed();
    Debug.Log((object) ("Generating level using seed " + (object) randomSeed));
    System.Random random = new System.Random(randomSeed);
    component2.TriggerLoads(random, this.NumberOfLevelChunksToUse);
  }

  public void OnLightProbesReady()
  {
    if (this.FinalOrderedChunks == null)
      return;
    foreach (MultiplayerLevelChunk finalOrderedChunk in this.FinalOrderedChunks)
      finalOrderedChunk.OnLightProbesReady();
  }

  public static void SendOutRandoms(IEnumerable<MultiplayerLevelChunk> orderedChunks, System.Random random)
  {
    foreach (MultiplayerLevelChunk orderedChunk in orderedChunks)
      orderedChunk.SupplyThoseThatNeedRandoms(random);
  }

  private void Update()
  {
    if (!this.sentLightProbesReady)
    {
      this.sentLightProbesReady = true;
      if (!(bool) (UnityEngine.Object) this.GetComponent<MultiplayerLevelInfoAdditive>())
        this.OnLightProbesReady();
    }
    if (PhotonNetwork.IsConnected)
      this.CheckAllPlayerLoadedLevel();
    if (!this.trackerStats.Check())
      return;
    this.PhotonStats.SetActive(!this.PhotonStats.activeSelf);
  }

  public override void OnMasterClientSwitched(Player newMasterClient) => this.CountdownTimer.enabled = true;

  private void Start()
  {
    if (!PhotonNetwork.IsConnected)
      return;
    this.OptionalInitializationEvents?.Invoke();
    if ((bool) (UnityEngine.Object) this.GetComponent<MultiplayerLevelInfoAdditive>())
      return;
    this.MarkLevelAsLoaded();
  }

  public void MarkLevelAsLoaded()
  {
    Hashtable propertiesToSet1 = new Hashtable();
    propertiesToSet1.Add((object) "PlayerLoadedLevel", (object) true);
    PhotonNetwork.LocalPlayer.SetCustomProperties(propertiesToSet1);
    if (PhotonNetwork.IsMasterClient || !CountdownTimer.TryGetStartTime(out int _))
      return;
    this.CountdownTimer.Initialize();
    if (!(bool) (UnityEngine.Object) this.GetComponent<MultiplayerLevelInfoAdditive>())
      return;
    Player localPlayer = PhotonNetwork.LocalPlayer;
    Hashtable propertiesToSet2 = new Hashtable();
    propertiesToSet2.Add((object) "JoinedLate", (object) true);
    localPlayer.SetCustomProperties(propertiesToSet2);
    foreach (MultiplayerLevelChunk finalOrderedChunk in this.FinalOrderedChunks)
      finalOrderedChunk.OnLocalPlayerJoinedLate?.Invoke();
  }

  public override void OnEnable()
  {
    base.OnEnable();
    if (PhotonNetwork.IsConnected && SceneManager.GetActiveScene().name != "MPLobby")
      this.TurnOnOffLocalPlayerMovement(false);
    CountdownTimer.OnCountdownTimerHasExpired += new CountdownTimer.CountdownTimerHasExpired(this.OnCountdownTimerIsExpired);
    if (!PhotonNetwork.IsConnected || !PhotonNetwork.IsMasterClient)
      return;
    this.StartCountdownTimerIfAllPlayersLoaded();
  }

  public override void OnDisable()
  {
    base.OnDisable();
    CountdownTimer.OnCountdownTimerHasExpired -= new CountdownTimer.CountdownTimerHasExpired(this.OnCountdownTimerIsExpired);
  }

  public override void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
  {
    if (!propertiesThatChanged.ContainsKey((object) "StartTime"))
      return;
    this.CountdownTimer.Initialize();
  }

  public override void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
  {
    if (!PhotonNetwork.IsMasterClient || !changedProps.ContainsKey((object) "PlayerLoadedLevel"))
      return;
    this.StartCountdownTimerIfAllPlayersLoaded();
  }

  private void StartCountdownTimerIfAllPlayersLoaded()
  {
    bool startTime = CountdownTimer.TryGetStartTime(out int _);
    if (!this.CheckAllPlayerLoadedLevel() || startTime)
      return;
    CountdownTimer.SetStartTime();
    this.OnAllPlayersLoaded?.Invoke();
  }

  public int TotalPlayers { get; private set; }

  public int LoadedPlayers { get; private set; }

  public bool CheckAllPlayerLoadedLevel()
  {
    Player[] playersInCurrentRoom = GameManager.GM.GetComponent<MultiplayerMode>().GetPlayersInCurrentRoom();
    this.TotalPlayers = playersInCurrentRoom.Length;
    this.LoadedPlayers = 0;
    foreach (Player player in playersInCurrentRoom)
    {
      object obj;
      if (player.CustomProperties.TryGetValue((object) "PlayerLoadedLevel", out obj) && (bool) obj)
        ++this.LoadedPlayers;
    }
    return this.LoadedPlayers == this.TotalPlayers;
  }

  private void OnCountdownTimerIsExpired()
  {
    if (this.countdownTimerFired)
      return;
    if (this.FinalOrderedChunks != null)
    {
      foreach (MultiplayerLevelChunk finalOrderedChunk in this.FinalOrderedChunks)
        finalOrderedChunk.OnAllPlayersReady();
    }
    this.TurnOnOffLocalPlayerMovement(true);
    this.countdownTimerFired = true;
  }

  public void SetRoomPropertiesRecentlyUsedChunks()
  {
    if (!PhotonNetwork.IsMasterClient || this.recentlyUsedChunkNames == null)
      return;
    string[] array = this.recentlyUsedChunkNames.ToArray<string>();
    Hashtable propertiesToSet = new Hashtable();
    propertiesToSet.Add((object) "recentlyUsedChunks", (object) array);
    PhotonNetwork.CurrentRoom.SetCustomProperties(propertiesToSet);
  }

  private void TurnOnOffLocalPlayerMovement(bool onOrOff) => GameManager.GM.PM.canControlAlt = onOrOff;

  public Transform GetNextSpawnPoint(bool getRealSpawnPoint)
  {
    int playerSlot = MultiplayerHelper.GetPlayerSlot(PhotonNetwork.LocalPlayer);
    if (!getRealSpawnPoint && this.TemporarySpawnPointsForAdditive != null && this.TemporarySpawnPointsForAdditive.Length != 0)
      return this.TemporarySpawnPointsForAdditive[Mathf.Clamp(playerSlot, 0, this.TemporarySpawnPointsForAdditive.Length - 1)];
    if (this.SpawnPoints == null)
      this.SpawnPoints = !(bool) (UnityEngine.Object) this.OptionalSpawnPointSearch ? this.GetComponentsInChildren<MultiplayerSpawnPoints>() : this.OptionalSpawnPointSearch.GetComponentsInChildren<MultiplayerSpawnPoints>();
    return this.SpawnPoints[Mathf.Clamp(playerSlot, 0, this.SpawnPoints.Length - 1)].transform;
  }

  public void AddKnownPosition(string name, FixedObjectAlongLevelPath obj) => this.knownPositions[name] = obj;

  public FixedObjectAlongLevelPath GetKnownPosition(string name)
  {
    FixedObjectAlongLevelPath objectAlongLevelPath;
    this.knownPositions.TryGetValue(name, out objectAlongLevelPath);
    return objectAlongLevelPath;
  }

  public void SetRecentlyStunnedPlayer(Player player) => this.recentlyStunnedPlayers.Add(player);

  public bool GetWasRecentlyStunned(Player player)
  {
    int num = this.recentlyStunnedPlayers.Contains(player) ? 1 : 0;
    if (num == 0)
      return num != 0;
    this.recentlyStunnedPlayers.Remove(player);
    return num != 0;
  }
}

MultiplayerPlayer#

Commands mentioned: mp

using Cinemachine;
using FMODUnity;
using Photon.Pun;
using Photon.Realtime;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;

public class MultiplayerPlayer : MonoBehaviourPun, IPunInstantiateMagicCallback, IPunObservable
{
  public AimingVisualization AimingVisualization;
  public Transform LookDirection;
  public TextMeshPro TextMesh;
  public CapsuleCollider[] CollidersDisableWhenMe;
  public GameObject RenderersDisableWhenMe;
  public GameObject PlayerMeshParent;
  public Material StunMaterial;
  public CapsuleCollider CapsuleToTestGoingThroughPortal;
  public GameObject CinemachineCameras;
  public MP_Local_Cosmetic_Switcher cosmeticSwitcher;
  public MOSTEventVOPlayer FinishLineVO;
  public VoiceLineCollection FinishLineVoices;
  private GameObject MyPlayer;
  private Vector3 localScale;
  private Vector3 inverseLocalScale;
  private bool wasMineOriginally;
  private bool finishedLevel;
  private float finishTime = float.MaxValue;
  public Player realOwner;
  private Vector3 MyResetPosition;
  private Quaternion MyResetRotation;
  private Vector3 MyResetScale;
  private float teleportDistanceThreshold = 3f;
  public bool HUDon;
  private GameObject MPHud;
  private GameObject GUICam;
  public GameObject AntiGravParticle;
  public GameObject MakeSmallParticle;
  public Material InvisibilityMaterial;
  public GameObject GrabBlameArrow;
  public GameObject NeedsRemotePlayerRigidBody;
  private float invisibleTimeLeft;
  private float invisibleTotalTime;
  private KeystrokeTracker typedMP;
  private MultiplayerLevelInfo levelInfo;
  private PortalManager portalManager;
  private GameObject grabbedObject;
  private CharacterController ccHack;
  private FPSInputController fpsInput;
  private bool couldControlLastFrame;
  private bool wasHovered;
  private HashSet<int> playersTargettingUs = new HashSet<int>();
  private float? timeTargeted = new float?(0.0f);
  private List<CinemachineVirtualCameraBase> cinemachineCams = new List<CinemachineVirtualCameraBase>();
  private Vector3 lastPosition;
  private int? originalOwnerNr;
  private int ogOwnerDebug;
  public WentThroughPortalAndWho OnTeleportThroughPortal;
  private bool shouldShowStun;
  private Material originalMaterial;
  private Coroutine showStun;
  private List<RememberMyOriginalMaterial> playerVisualsWorker = new List<RememberMyOriginalMaterial>();
  private bool wasShowingInvisibility;
  private Player lastOwner;
  private Coroutine blameArrowRoutine;

  public GameObject BlameArrowParent { get; private set; }

  public float? InvisibleAmount
  {
    get
    {
      float? nullable = new float?();
      return (double) this.invisibleTimeLeft > 0.0 ? new float?(this.invisibleTimeLeft / this.invisibleTotalTime) : nullable;
    }
  }

  public void SetInvisibleTime(float time)
  {
    this.invisibleTimeLeft = time;
    this.invisibleTotalTime = time;
  }

  private void Awake()
  {
    if ((bool) (Object) this.GrabBlameArrow)
    {
      this.GrabBlameArrow.SetActive(false);
      this.BlameArrowParent = this.GrabBlameArrow.transform.parent.gameObject;
    }
    if (!this.originalOwnerNr.HasValue)
      this.originalOwnerNr = new int?(this.GetComponent<PhotonView>().OwnerActorNr);
    this.MyPlayer = this.gameObject;
    this.localScale = this.transform.localScale;
    this.inverseLocalScale = new Vector3(1f / this.localScale.x, 1f / this.localScale.y, 1f / this.localScale.z);
    if (this.photonView.IsMine && !(bool) (Object) GameManager.GM.player)
      GameManager.GM.AttachPlayer(this.gameObject);
    else
      this.gameObject.layer = MoSTLayer.CanGrab;
    PhotonTransformViewPositionModel positionModel = this.GetComponent<PhotonTransformViewClassic>().m_PositionModel;
    if (!positionModel.TeleportEnabled)
      return;
    this.teleportDistanceThreshold = positionModel.TeleportIfDistanceGreaterThan;
  }

  private void _AddRigidBodyToRemotePlayersSoTheyCanOpenDoors()
  {
    if (this.IsClone() || this.IsMainLocalPlayer || !(bool) (Object) this.NeedsRemotePlayerRigidBody)
      return;
    Rigidbody rigidbody = this.NeedsRemotePlayerRigidBody.AddComponent<Rigidbody>();
    rigidbody.mass = 1E-06f;
    rigidbody.drag = 0.0f;
    rigidbody.angularDrag = 0.5f;
    rigidbody.useGravity = false;
    rigidbody.isKinematic = true;
  }

  private void Start()
  {
    MultiplayerMode component = GameManager.GM.GetComponent<MultiplayerMode>();
    component.OnCreatePlayer(this.gameObject);
    this.portalManager = PortalInstanceTracker.instance.PortalManager;
    this.portalManager.OnTeleport += new global::WentThroughPortal(this.SendWentThroughPortal);
    this.levelInfo = component.LevelInfo;
    if ((bool) (Object) this.levelInfo && this.levelInfo.IsPlayerCloneable)
      this.GetComponent<DropTriggerScript>().grabValues.isCloneable = true;
    this._AddRigidBodyToRemotePlayersSoTheyCanOpenDoors();
    if (!this.IsClone())
      this.cosmeticSwitcher.TellOthersToUpdateMyCosmetics();
    if (this.IsMainLocalPlayer)
    {
      foreach (Collider collider in this.CollidersDisableWhenMe)
        collider.enabled = false;
      foreach (Renderer componentsInChild in this.RenderersDisableWhenMe.GetComponentsInChildren<MeshRenderer>())
        componentsInChild.enabled = false;
    }
    this.GetComponent<StunPlayerWhenHitByGrabObject>().enabled = this.IsMainLocalPlayer;
    this.realOwner = this.photonView.Owner.Get(this.originalOwnerNr.Value);
    this.TextMesh.text = this.realOwner.NickName;
    if (!this.IsMainLocalPlayer)
    {
      this.GetComponent<FaceGrabberWhenGrabbed>().GrabbedPostProcess.gameObject.SetActive(false);
      this.GetComponent<FaceGrabberWhenGrabbed>().enabled = false;
      MouseLook[] componentsInChildren = this.GetComponentsInChildren<MouseLook>();
      if (!this.IsLocalPlayerOrCloneOf())
      {
        foreach (Behaviour behaviour in componentsInChildren)
          behaviour.enabled = false;
      }
      foreach (Behaviour componentsInChild in this.GetComponentsInChildren<Camera>())
        componentsInChild.enabled = false;
      foreach (Behaviour componentsInChild in this.GetComponentsInChildren<CameraThatSeesPortals>())
        componentsInChild.enabled = false;
      this.GetComponentInChildren<StudioListener>().enabled = false;
      this.GetComponentInChildren<PlayerMovementSoundController>().enabled = false;
      this.GetComponentInChildren<AudioListener>().enabled = false;
      this.GetComponentInChildren<ResizeScript>().enabled = false;
      this.GetComponentInChildren<ResizeScriptPartTwo>().enabled = false;
      this.GetComponentInChildren<PlayerLerpMantle>().enabled = false;
    }
    else
      this.GetComponent<DropTriggerScript>().enabled = false;
    this.MyPlayer.GetComponent<PlayerResizer>().ForceNeverChangeGravity();
    this.ccHack = this.MyPlayer.GetComponent<CharacterController>();
    this.fpsInput = this.GetComponentInChildren<FPSInputController>();
    this.wasMineOriginally = this.MyPlayer.GetComponent<PhotonView>().IsMine;
    if (this.wasMineOriginally)
    {
      this.GetComponent<PhotonTransformViewClassic>().m_PositionModel.TeleportEnabled = false;
    }
    else
    {
      this.ccHack.enabled = false;
      this.fpsInput.enabled = false;
    }
    this.HUDon = true;
    this.MPHud = GameObject.Find("UI_PAUSE_MENU").transform.Find("Canvas").transform.Find("MultiplayerHUD").gameObject;
    this.GUICam = this.transform.Find("GUI Camera").gameObject;
    this.MaybeStealCosmetics();
    this.SetMyResetTransform();
    this.typedMP = new KeystrokeTracker()
    {
      KeyCodes = new KeyCode[2]{ KeyCode.M, KeyCode.P }
    };
  }

  private void MaybeStealCosmetics()
  {
    if (!this.IsClone())
      return;
    MP_Local_Cosmetic_Switcher componentInChildren = this.GetComponent<DropTriggerScript>().cloneRoot.GetComponentInChildren<MP_Local_Cosmetic_Switcher>();
    if (!(bool) (Object) componentInChildren)
      return;
    this.GetComponentInChildren<MP_Local_Cosmetic_Switcher>().GrabCosmeticsFromThisCosmeticSwitcher(componentInChildren);
  }

  public bool IsMainLocalPlayer => (Object) GameManager.GM.player == (Object) this.gameObject;

  public bool IsLocalPlayerOrCloneOf() => this.originalOwnerNr.HasValue ? this.originalOwnerNr.Value == PhotonNetwork.LocalPlayer.ActorNumber : this.photonView.IsMine;

  private static LayerMask GetPhysicsLayerMask(int currentLayer)
  {
    int num = 0;
    for (int layer2 = 0; layer2 < 32; ++layer2)
    {
      if (!Physics.GetIgnoreLayerCollision(currentLayer, layer2))
        num |= 1 << layer2;
    }
    return (LayerMask) num;
  }

  public void SetGrabbedObject(GameObject grabbedObject)
  {
    this.grabbedObject = grabbedObject;
    this.UpdateAimingVisualization();
  }

  public void UnSetGrabbedObjectIfItsMe(GameObject me)
  {
    if (!((Object) this.grabbedObject == (Object) me))
      return;
    this.SetGrabbedObject((GameObject) null);
  }

  private void Update()
  {
    this._UpdateInvisibility();
    if (this.originalOwnerNr.HasValue)
      this.ogOwnerDebug = this.originalOwnerNr.Value;
    bool flag = this.MyPlayer.GetComponent<PhotonView>().IsMine && this.originalOwnerNr.Value == PhotonNetwork.LocalPlayer.ActorNumber && this.MyPlayer.layer != MoSTLayer.Grabbed;
    if (!flag)
    {
      this.ccHack.enabled = false;
      this.fpsInput.enabled = false;
    }
    else
    {
      PlayerSizeBoundsVolumeManager.Instance.UpdatePlayerSize(this.GetComponent<PlayerResizer>(), this.transform);
      if (flag && !this.couldControlLastFrame)
      {
        if (!this.ccHack.enabled)
          this.GetComponent<PlayerResizer>().Poke();
        this.ccHack.enabled = true;
        this.fpsInput.enabled = true;
      }
      else if (!flag)
      {
        this.ccHack.enabled = false;
        this.fpsInput.enabled = false;
      }
    }
    this.couldControlLastFrame = flag;
    this.EvaluateRacePosition();
    if (this.finishedLevel)
      this.CinemachineCameras.SetActive(false);
    if (this.CinemachineCameras.activeSelf && (double) Vector3.Distance(this.lastPosition, this.transform.position) > (double) this.teleportDistanceThreshold)
    {
      this.cinemachineCams.Clear();
      this.CinemachineCameras.GetComponentsInChildren<CinemachineVirtualCameraBase>((List<M0>) this.cinemachineCams);
      foreach (CinemachineVirtualCameraBase cinemachineCam in this.cinemachineCams)
        cinemachineCam.PreviousStateIsValid = false;
    }
    this.lastPosition = this.transform.position;
    this._DetectWhenSomeoneIsTargettingUsAndTellOurOwner();
    this._CalculateHowLongWeveBeenTargeted();
    if (GameManager.GM.CanUseKeyboardHotKeys() && this.typedMP.Check())
    {
      if (this.HUDon)
      {
        this.MPHud.SetActive(false);
        this.HUDon = false;
      }
      else
      {
        this.MPHud.SetActive(true);
        this.HUDon = true;
      }
    }
    this._UpdatePlayerVisualsBasedOnState();
    this._UpdateBlameArrow();
  }

  private void _DetectWhenSomeoneIsTargettingUsAndTellOurOwner()
  {
    DropTriggerScript component = this.GetComponent<DropTriggerScript>();
    if (component.IsHovered == this.wasHovered)
      return;
    this.GetComponent<PhotonView>().RPC("YouAreTargeted", this.realOwner, (object) component.IsHovered, (object) PhotonNetwork.LocalPlayer.ActorNumber);
    this.wasHovered = component.IsHovered;
  }

  [PunRPC]
  public void YouAreTargeted(bool targetted, int byWhomActorNr)
  {
    if (targetted)
      this.playersTargettingUs.Add(byWhomActorNr);
    else
      this.playersTargettingUs.Remove(byWhomActorNr);
  }

  private void _CalculateHowLongWeveBeenTargeted()
  {
    if (this.playersTargettingUs.Count > 0)
    {
      if (!this.timeTargeted.HasValue)
        this.timeTargeted = new float?(0.0f);
      this.timeTargeted = new float?(this.timeTargeted.Value + Time.deltaTime);
    }
    else
      this.timeTargeted = new float?();
  }

  public float? AmIBeingTargeted() => this.timeTargeted;

  private void OnDestroy()
  {
    if ((bool) (Object) this.portalManager)
      this.portalManager.OnTeleport -= new global::WentThroughPortal(this.SendWentThroughPortal);
    if ((bool) (Object) GameManager.GM)
      GameManager.GM.GetComponent<MultiplayerMode>().OnDestroyPlayer(this.gameObject);
    if (!this.IsMainLocalPlayer || !PhotonNetwork.InRoom)
      return;
    PhotonNetwork.DestroyPlayerObjects(PhotonNetwork.LocalPlayer);
  }

  [PunRPC]
  private void SetDropPoint(
    Vector3 position,
    Quaternion rotation,
    Vector3 localScale,
    Vector3 exGrabberPosition,
    Vector3 exGrabberUp)
  {
    this.transform.position = position;
    this.transform.rotation = rotation;
    this.transform.localScale = localScale;
    float x;
    float y;
    FaceGrabberWhenGrabbed.GetDesiredMouseLookAngles(GameManager.GM.playerCamera.transform, exGrabberPosition, exGrabberUp, out x, out y);
    this.GetComponent<FaceGrabberWhenGrabbed>().SetMouseLookRotations(x, y);
  }

  public void OnDroppedLocal()
  {
    PhotonView component = this.MyPlayer.GetComponent<PhotonView>();
    if (!this.originalOwnerNr.HasValue)
      return;
    int ownerActorNr = component.OwnerActorNr;
    int? originalOwnerNr = this.originalOwnerNr;
    int valueOrDefault = originalOwnerNr.GetValueOrDefault();
    if (ownerActorNr == valueOrDefault & originalOwnerNr.HasValue)
      return;
    component.TransferOwnership(this.originalOwnerNr.Value);
    Transform transform = GameManager.GM.player.transform;
    component.RPC("SetDropPoint", PhotonNetwork.CurrentRoom.GetPlayer(this.originalOwnerNr.Value), (object) this.transform.position, (object) this.transform.rotation, (object) this.transform.localScale, (object) transform.position, (object) transform.up);
  }

  private void LateUpdate()
  {
    this.UpdateAimingVisualization();
    this.TextMesh.transform.rotation = GameManager.GM.playerCamera.transform.rotation;
  }

  private void UpdateAimingVisualization()
  {
    if ((bool) (Object) this.grabbedObject && !this.IsMainLocalPlayer)
    {
      this.AimingVisualization.gameObject.SetActive(true);
      this.AimingVisualization.Aim(this.LookDirection, this.grabbedObject.transform, this.grabbedObject);
    }
    else
      this.AimingVisualization.gameObject.SetActive(false);
  }

  public int GetSpecifiedOwnerId() => this.originalOwnerNr.Value;

  public bool CanClonePlayer_AndMaybeDestroy()
  {
    if (this.photonView.Owner.Get(this.originalOwnerNr.Value) != null)
      return true;
    if (this.photonView.AmOwner)
      PhotonNetwork.Destroy(this.gameObject);
    return false;
  }

  public void OnPhotonInstantiate(PhotonMessageInfo info)
  {
    int? playerNumberFromClone = MultiplayerHelper.MaybeExtractOriginalPlayerNumberFromClone(this.gameObject);
    if (!playerNumberFromClone.HasValue)
      return;
    this.originalOwnerNr = playerNumberFromClone;
    this.GetComponent<ReturnPlayerToNormalSize>().enabled = false;
  }

  private void OnTriggerEnter(Collider other)
  {
    if (other.gameObject.CompareTag("LavaMP"))
      this.gameObject.SetActive(false);
    if (other.gameObject.CompareTag("MPResetSpot"))
      this.SetMyResetTransform();
    MysteryPowerupBox componentInParent = other.gameObject.GetComponentInParent<MysteryPowerupBox>();
    if ((bool) (Object) componentInParent && this.IsLocalPlayerOrCloneOf())
      componentInParent.Open();
    if (!((Object) other.gameObject.GetComponent<ResetGrabbableObject>() != (Object) null) || !other.gameObject.GetComponent<ResetGrabbableObject>().ResetMPPlayer)
      return;
    this.ResetToMyResetTransform();
  }

  private bool IsClone() => (bool) (Object) this.GetComponent<DropTriggerScript>().cloneParent;

  public void EvaluateRacePosition()
  {
    if (this.IsClone() || !(bool) (Object) this.levelInfo)
      return;
    if (MultiplayerHelper.DidPlayerJoinLate(this.realOwner))
      this.levelInfo.PlayerPath.SetPlayerPositionAlongLevel(this.levelInfo.PlayerPath.StartNode.OriginalPosition, this.GetComponent<PhotonView>().CreatorActorNr, this.finishedLevel ? new float?(this.finishTime) : new float?());
    else
      this.levelInfo.PlayerPath.SetPlayerPositionAlongLevel(this.transform.position, this.GetComponent<PhotonView>().CreatorActorNr, this.finishedLevel ? new float?(this.finishTime) : new float?());
  }

  public bool HasFinishedLevel() => this.finishedLevel;

  [PunRPC]
  public void PhotonSetFinishedLevel(float time)
  {
    this.finishedLevel = true;
    this.finishTime = time;
  }

  public void SetFinishedLevel()
  {
    this.GetComponent<PhotonView>().RPC("PhotonSetFinishedLevel", RpcTarget.AllBuffered, (object) this.GetTimeSinceLevelLoad());
    if (!this.levelInfo.LevelProfile.IsCampaign)
    {
      int rankingForPlayer = this.levelInfo.PlayerPath.GetRankingForPlayer(this.realOwner);
      if (rankingForPlayer < this.FinishLineVoices.VoiceLines.Length)
      {
        this.FinishLineVO.GetComponent<StudioEventEmitter>().Event = this.FinishLineVoices.VoiceLines[rankingForPlayer].Event;
        this.FinishLineVO.gameObject.SetActive(true);
      }
    }
    List<MultiplayerPlayer> results = new List<MultiplayerPlayer>();
    MultiplayerHelper.GetPlayerComponentsNonAlloc<MultiplayerPlayer>(results, false);
    foreach (Component component in results)
      component.gameObject.layer = MoSTLayer.Default;
  }

  public void SendWentThroughPortal(Portal source)
  {
    PhotonView component = source.GetComponent<PhotonView>();
    if (!(bool) (Object) component)
      return;
    WentThroughPortalAndWho teleportThroughPortal = this.OnTeleportThroughPortal;
    if (teleportThroughPortal != null)
      teleportThroughPortal(source, this);
    this.GetComponent<PhotonView>().RPC("WentThroughPortal", RpcTarget.Others, (object) component.ViewID);
  }

  [PunRPC]
  private void WentThroughPortal(int sourcePortalViewId)
  {
    PhotonView photonView = PhotonView.Find(sourcePortalViewId);
    if (!(bool) (Object) photonView)
      return;
    Portal component = photonView.GetComponent<Portal>();
    if (!(bool) (Object) component || !(bool) (Object) component.Destination)
      return;
    WentThroughPortalAndWho teleportThroughPortal = this.OnTeleportThroughPortal;
    if (teleportThroughPortal != null)
      teleportThroughPortal(component, this);
    this.GetComponent<PhotonTransformViewClassic>().SetFromToTeleportTransform(component.ThisSide, component.OtherSide.transform);
  }

  [PunRPC]
  public void IGotStunned(int playerResponsibleActorNr)
  {
    if (this.showStun != null)
      this.StopCoroutine(this.showStun);
    this.showStun = this.StartCoroutine(this.ShowStun());
    if (playerResponsibleActorNr != PhotonNetwork.LocalPlayer.ActorNumber || !(bool) (Object) this.levelInfo)
      return;
    this.levelInfo.SetRecentlyStunnedPlayer(this.realOwner);
  }

  [PunRPC]
  public void StunRemotePlayer(float stunIntensity, float stunTime, int playerResponsibleActorNr)
  {
    if (!this.IsMainLocalPlayer)
      return;
    this.GetComponent<PlayerBuff>().SetWalkSpeedMultiplier(stunIntensity, 1f, stunTime, PhotonNetwork.CurrentRoom.GetPlayer(playerResponsibleActorNr));
  }

  private IEnumerator ShowStun()
  {
    this.shouldShowStun = true;
    yield return (object) new WaitForSeconds(2f);
    this.shouldShowStun = false;
  }

  private void _UpdateInvisibility() => this.invisibleTimeLeft = Mathf.Max(0.0f, this.invisibleTimeLeft - Time.deltaTime);

  private void _UpdatePlayerVisualsBasedOnState()
  {
    bool isInvisible = false;
    this.PlayerMeshParent.GetComponentsInChildren<RememberMyOriginalMaterial>(true, (List<M0>) this.playerVisualsWorker);
    if (this.shouldShowStun)
    {
      foreach (RememberMyOriginalMaterial originalMaterial in this.playerVisualsWorker)
        originalMaterial.MeshRenderer.sharedMaterial = this.StunMaterial;
    }
    else if (this.InvisibleAmount.HasValue)
    {
      foreach (RememberMyOriginalMaterial originalMaterial in this.playerVisualsWorker)
        originalMaterial.MeshRenderer.sharedMaterial = this.InvisibilityMaterial;
      isInvisible = true;
    }
    else
    {
      foreach (RememberMyOriginalMaterial originalMaterial in this.playerVisualsWorker)
        originalMaterial.MeshRenderer.sharedMaterial = originalMaterial.OriginalMaterial;
    }
    this._SetInvisibilityVisuals(isInvisible);
  }

  private void _SetInvisibilityVisuals(bool isInvisible)
  {
    this.wasShowingInvisibility = isInvisible;
    this.TextMesh.gameObject.SetActive(!isInvisible);
    this.RenderersDisableWhenMe.GetComponent<MP_Local_Cosmetic_Switcher>().CenterOfHead.gameObject.SetActive(!isInvisible);
    this.RenderersDisableWhenMe.GetComponent<MP_Local_Cosmetic_Switcher>().HatParent.gameObject.SetActive(!isInvisible);
    if (!(bool) (Object) this.BlameArrowParent)
      return;
    this.BlameArrowParent.SetActive(!isInvisible);
  }

  public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
  {
    if (stream.IsWriting)
      return;
    this.GetComponent<FaceGrabberWhenGrabbed>().RestoreLookAfterGettingSyncFromGrabber();
  }

  private float GetTimeSinceLevelLoad() => (bool) (Object) this.levelInfo && PhotonNetwork.IsConnected ? this.levelInfo.CountdownTimer.GetSynchronizedLevelTime() : Time.timeSinceLevelLoad;

  public float GetFinishTime() => this.finishTime;

  public void SetMyResetTransform()
  {
    this.MyResetPosition = this.transform.position;
    this.MyResetRotation = this.transform.rotation;
    this.MyResetScale = this.transform.localScale;
  }

  public void ResetToMyResetTransform()
  {
    this.transform.position = this.MyResetPosition;
    this.transform.rotation = this.MyResetRotation;
    this.transform.localScale = this.MyResetScale;
    this.GetComponent<PlayerResizer>().Poke();
  }

  private void _UpdateBlameArrow()
  {
    if (!this.IsMainLocalPlayer)
      return;
    Player owner = this.photonView.Owner;
    if (owner == this.lastOwner)
      return;
    if (owner == PhotonNetwork.LocalPlayer && this.lastOwner != null)
    {
      GameObject playerObjectForPlayer = GameManager.GM.GetComponent<MultiplayerMode>().GetPlayerObjectForPlayer(this.lastOwner);
      if ((bool) (Object) playerObjectForPlayer)
        playerObjectForPlayer.GetComponent<MultiplayerPlayer>().ShowGrabBlameArrow();
    }
    this.lastOwner = owner;
  }

  private void ShowGrabBlameArrow()
  {
    if (!(bool) (Object) this.GrabBlameArrow)
      return;
    if (this.blameArrowRoutine != null)
      this.StopCoroutine(this.blameArrowRoutine);
    this.blameArrowRoutine = this.StartCoroutine(this.ShowGrabBlameArrowFor(5f));
  }

  private IEnumerator ShowGrabBlameArrowFor(float time)
  {
    this.GrabBlameArrow.SetActive(true);
    yield return (object) new WaitForSeconds(time);
    this.GrabBlameArrow.SetActive(false);
  }
}

PopulateLoadingScreenList#

Commands mentioned: db

using System.IO;
using UnityEngine;
using UnityEngine.UI;

public class PopulateLoadingScreenList : MonoBehaviour
{
  public static int? SaveChosenLoadingScreen;
  public GameObject UnlockedLevelButtonTemplate;
  private readonly KeystrokeTracker tracker = new KeystrokeTracker()
  {
    KeyCodes = new KeyCode[2]{ KeyCode.D, KeyCode.B }
  };
  private bool madeButtons;

  private void Update()
  {
    if (!GameManager.GM.enableDebugFunctions || this.madeButtons || !this.tracker.Check())
      return;
    this.madeButtons = true;
    this._MakeButton("Normal loading screen", -1);
    SceneReference[] randomLoadingScreens = GameManager.GM.LevelInfo.RandomLoadingScreens;
    for (int loadingIndex = 0; loadingIndex < randomLoadingScreens.Length; ++loadingIndex)
      this._MakeButton(randomLoadingScreens[loadingIndex].ScenePath, loadingIndex);
    LayoutRebuilder.MarkLayoutForRebuild(this.transform as RectTransform);
  }

  private void _MakeButton(string loadingScenePath, int loadingIndex)
  {
    GameObject gameObject = Object.Instantiate<GameObject>(this.UnlockedLevelButtonTemplate, this.transform);
    gameObject.GetComponent<StartSpecificLevelScript>().SetLoadingScreenIndexOverride(loadingIndex);
    string withoutExtension = Path.GetFileNameWithoutExtension(loadingScenePath);
    gameObject.GetComponent<Text>().text = withoutExtension;
    gameObject.SetActive(true);
  }
}

PopulateUnlockedLevelList#

Commands mentioned: db

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class PopulateUnlockedLevelList : MonoBehaviour
{
  public GameObject UnlockedLevelButtonTemplate;
  private readonly KeystrokeTracker tracker = new KeystrokeTracker()
  {
    KeyCodes = new KeyCode[2]{ KeyCode.D, KeyCode.B }
  };
  private bool madeButtons;

  private void Update()
  {
    if (!GameManager.GM.enableDebugFunctions || this.madeButtons || !this.tracker.Check())
      return;
    this.madeButtons = true;
    this._MakeButtons(GameManager.GM.GetComponent<SaveAndCheckpointManager>().GetUnlockedLevelList());
    this._MakeButtons(GameManager.GM.GetComponent<SaveAndCheckpointManager>().GetLockedLevelList(), new Color?(Color.red));
    LayoutRebuilder.MarkLayoutForRebuild(this.transform as RectTransform);
  }

  private void _MakeButtons(List<string> levelNames, Color? optionalColor = null)
  {
    foreach (string levelName in levelNames)
    {
      GameObject gameObject = Object.Instantiate<GameObject>(this.UnlockedLevelButtonTemplate, this.transform);
      gameObject.GetComponent<StartSpecificLevelScript>().LevelSaveName = levelName;
      if (GameManager.GM.GetComponent<MiniChallengeMode>().MiniChallengeModeEnabled && gameObject.GetComponent<StartSpecificLevelScript>().LevelSaveName == "EndingMontage")
        gameObject.SetActive(false);
      gameObject.GetComponent<Text>().text = levelName;
      if (optionalColor.HasValue)
        gameObject.GetComponent<Text>().color = optionalColor.Value;
      gameObject.SetActive(true);
    }
  }
}

ReleaseTheBalls#

Commands mentioned: ball

using System.Collections.Generic;
using UnityEngine;

public class ReleaseTheBalls : MonoBehaviour
{
  public TestCollisionBall CollisionBallPrefab;
  public Transform WorldCollidePlanePrefab;
  public Transform ActiveBallsParent;
  public Transform FrozenBallsParent;
  public int BallsToRelease = 20;
  public float BallVelocity = 2f;
  private KeystrokeTracker keyTracker;
  private Vector3 worldCenter;
  private float worldRadius;
  private Transform worldCollider;
  private readonly List<TestCollisionBall> collisionBalls = new List<TestCollisionBall>();

  private void Start() => this.keyTracker = new KeystrokeTracker()
  {
    KeyCodes = new KeyCode[4]
    {
      KeyCode.B,
      KeyCode.A,
      KeyCode.L,
      KeyCode.L
    }
  };

  private void Update()
  {
  }

  private void ReleaseBalls()
  {
    if (!(bool) (Object) this.worldCollider)
      this.ComputeWorldBounds();
    for (int index = 0; index < this.BallsToRelease; ++index)
    {
      TestCollisionBall testCollisionBall = Object.Instantiate<TestCollisionBall>(this.CollisionBallPrefab, this.ActiveBallsParent);
      CapsuleCollider component1 = testCollisionBall.GetComponent<CapsuleCollider>();
      if ((bool) (Object) component1)
      {
        CharacterController component2 = GameManager.GM.player.GetComponent<CharacterController>();
        component1.radius = component2.radius;
        component1.height = component2.height;
        component1.center = component2.center;
        testCollisionBall.transform.position = component2.transform.position;
      }
      testCollisionBall.GetComponent<Rigidbody>().AddForce(Random.insideUnitSphere * this.BallVelocity, ForceMode.VelocityChange);
    }
  }

  private void ComputeWorldBounds()
  {
    Vector3 rhs1 = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
    Vector3 rhs2 = new Vector3(float.MinValue, float.MinValue, float.MinValue);
    foreach (Renderer renderer in Object.FindObjectsOfType<Renderer>())
    {
      Bounds bounds = renderer.bounds;
      rhs1 = Vector3.Min(bounds.min, rhs1);
      bounds = renderer.bounds;
      rhs2 = Vector3.Max(bounds.max, rhs2);
    }
    this.worldCenter = (rhs2 + rhs1) * 0.5f;
    this.worldRadius = (rhs2 - rhs1).magnitude * 0.5f;
    Transform transform = Object.Instantiate<Transform>(this.WorldCollidePlanePrefab, this.transform);
    transform.position = this.worldCenter;
    transform.localScale = Vector3.one * this.worldRadius * 0.5f;
    this.worldCollider = transform;
    this.transform.SetParent((Transform) null, true);
  }
}

ResizeScript#

Commands mentioned: rty

using Photon.Pun;
using Rewired;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

public class ResizeScript : MonoBehaviour, IPunOwnershipCallbacks
{
  [NonSerialized]
  public bool AllowScrollPlacement;
  public bool isEnableDebug;
  [Tooltip("Try to figure out the spherical-coordinates bounds of grabbed objects so we don't ignore their off-screen parts.")]
  public bool UseSphericalBounds = true;
  [Tooltip("Avoid the dropped object overlapping with the player capsule by artificially shrinking it.")]
  public bool UseOverlapForAvoidingPlayerCollision = true;
  [Tooltip("We'll make no attempt to avoid player overlap when dropping objects below this large in size.")]
  public float SmallObjectIgnoreOverlapThreshold = 1f;
  private const float SAMPLE_DENSITY_SCREEN = 20f;
  private const int MAX_SAMPLE_PER_EDGE = 40;
  private const int MIN_SAMPLE_PER_EDGE = 20;
  public const int MaxCountAllowedToUseMeshVerts = 200;
  private const int MaxRayCount = 1881;
  public ResizeInfo Info;
  public GrantAchievement CloneAlotAchievement;
  [NonSerialized]
  public CreateCreated OnCloneCreated;
  public MultiplayerGrabSettings MultiplayerGrabSettings;
  private bool isScrolling;
  private bool _hasSelection;
  private bool _isGrabbing;
  private GameObject grabbedObject;
  public bool isPointingAtInstantProjectObj;
  private Quaternion grabbedObjectRotationInCameraSpaceOriginal;
  private Quaternion grabbedObjectRotationInWorldSpaceOriginal;
  private Vector3 positionInCameraSpaceOriginal;
  private Vector3 positionInCameraSpaceOriginalFinal;
  private Vector3 accumulatedPlayerRotationCameraSpaceSelfRightingLock;
  public bool isReadyToGrab;
  public bool isObjectBlocked;
  public bool isObjectReadyToReturn;
  private bool notAllowedToGrab;
  private bool notAllowedToGrabNextFrame;
  private bool turnOffGrabDeniedSoundNextFrame;
  public SoundEffectScript soundEffectScript;
  private Material DrawOutlineMat;
  public PostProcessCamera drawOutlinePostProcessing;
  private Color canSpinColor = new Color(1f, 1f, 1f, 1f);
  private Color canFollowColor = new Color(1f, 0.3f, 0.3f, 1f);
  private Color cannotDoAnythingColor = new Color(0.0f, 0.0f, 0.0f, 1f);
  private MouseLook mouseLook1;
  private MouseLook mouseLook2;
  private bool isRejectProject;
  private bool toResizeWithoutDropping;
  private const float MinGrabDistance = 0.25f;
  private bool justDroppedThisFrame;
  private Color? outlineOverrideColor;
  private float _maxGrabDistance = 400f;
  private bool isObjectInSky;
  private int _layerMaskIgnoreGrabbed;
  private int _layerMaskGrabbed;
  private int _layerMaskIgnorePlayer;
  private int _layerMaskOnlyPlayer;
  public Texture SpinInstruction;
  public Texture DropInstruction;
  public PostProcessCamera BlockedPostProcessing;
  public Material blockedMat;
  public OutlinerCamera outlinerCamera;
  private bool isLerpingToPosition;
  private Vector3 prevPosition = Vector3.zero;
  public bool dontLerpObjectsToCenter;
  public bool immediatelyDropObjects;
  public MOSTTriggerOnXDrops triggerOnDrops;
  private GameObject oldObj;
  public int repeatInstantProjectCount;
  public int repeatInstantProjectMax;
  private const float HoldRotateTutorialTimerBase = 3f;
  private float holdRotateTutorialTimer;
  public bool doRotateTutInThisLevel;
  public Image rotateTut;
  [Tooltip("Min/max range for adding a random rotation when an object is dropped.")]
  public Vector2 RandomTorqueOnDrop = Vector2.zero;
  [Tooltip("Should random torque be limited to a plane, so that the object has less chance of rotating into a wall and bouncing out.")]
  public bool LimitRandomTorqueToCameraPlane = true;
  [Tooltip("World sized radius for grab object hit testing.")]
  public float CastRadius = 0.1f;
  [Tooltip("World sized radius for grab object hit testing for controllers.")]
  public float CastRadiusForController = 0.2f;
  public float AssistCastRadius = 0.2f;
  public float AssistCastDistance = 10f;
  private KeystrokeTracker keyTracker;
  public ChallengeMode _ChallengeMode;
  public MiniChallengeMode _MiniChallengeMode;
  public bool IsMultiplayerPlayer;
  public UnityEvent OnDropped;
  public UnityEvent OnGrabbed;
  public ResizeDroppedEvent OnDroppedParam;
  public ResizeDroppedEvent OnGrabbedParam;
  [NonSerialized]
  public DenyGrab DenyGrab;
  public Material SnapMaterial;
  private bool hasGrabRestrictions;
  private bool isCampaign;
  private float hoverTimeModifierDuration;
  private float hoverTimeModifier = 1f;
  private GameObject lastHoverObject;
  private float grabRecoveryCountdown;
  private float grabRecoveryTime;
  private float forceLetGoCountdown;
  private float forceLetGoTime;
  private GameObject lastGrabbedObject;
  private float curLerpingTime;
  private const float MaxLerpingTime = 0.8f;
  private Portal lastCrossedPortal;
  private MaterialPool fadeMaterialPool;
  private const float AlphaFade = 0.5f;
  private const float TooSmallEpsilon = 0.0001f;
  private bool continueInLateLateUpdate;
  private List<SmartSnapResult> snapWorker = new List<SmartSnapResult>();
  public Vector3 spinGUIStartinPoint;
  public Vector3 dropGUIStartinPoint;
  private static RaycastHit[] hitWorker = new RaycastHit[20];
  private const float Smidgen = 0.1f;
  private static readonly Collider[] lotsOfColliders = new Collider[100];
  private const int MaxIterations = 10;
  private List<Ray> rayListWorker = new List<Ray>();
  private List<Vector3> objWorldSpacePoints = new List<Vector3>();
  private List<Vector3> objPoints = new List<Vector3>();
  private const float PlatformRayReduction = 1f;
  public float TestingRayReduction = 1f;
  private const float RaysPerDegree = 0.5f;
  public GrabObjectRayCastType RayCastType;
  private List<Vector3> rayDirectionsWorkerPrelim = new List<Vector3>();
  private List<Vector3> rayDirectionsWorkerFinal = new List<Vector3>();
  private NativeArray<RaycastHit> rayCastResults;
  private NativeList<RaycastCommand> rayCastCommands;
  private NativeArray<RaycastHit> rayCastResultsPortal;
  private NativeList<RaycastCommand> rayCastCommandsPortal;
  private List<ResizeScript.PortalAndIndex> portalCommandToOriginalIndex = new List<ResizeScript.PortalAndIndex>();
  private List<Portal> portalsWeHit = new List<Portal>();
  private Matrix4x4[] portalMatrices = new Matrix4x4[100];
  private List<float> forwardHitDistances = new List<float>();
  private const float extraDistanceForComplexPieces = 0.0f;
  private NativeList<int> filteredRayIndices;
  private int portalRayCount;
  private int returnRayCount;
  private JobHandle handleToWaitFor;
  private static readonly string StopProjectionTag = "Stop projection";
  private static readonly string ChildThatIgnoresGrabTag = "ChildThatIgnoresGrab";
  private readonly Stopwatch swTotal = new Stopwatch();
  private readonly Stopwatch swInclusive = new Stopwatch();
  private readonly Stopwatch swEnsureNoPlayerCollide = new Stopwatch();
  private readonly Stopwatch swCalcBounds = new Stopwatch();
  private readonly Stopwatch swHitGrab = new Stopwatch();
  private Vector3 scaleAtMinDistance;
  private float massAtMinDistance;
  private float grabbedMinGrabDistance;
  public const float DefaultDistanceScaleModifier = 0.99f;
  private Vector3 scrollWorldAxis;
  private bool wasKinematic;
  private Vector3 mouseOffset;
  private Plane facingPlane;
  private Vector3 originalGrabbObjectPosition;
  private const float CounterZFightingAmount = 0.001f;

  public bool hasSelection
  {
    get => this._hasSelection;
    set
    {
      this._hasSelection = value;
      this.drawOutlinePostProcessing.enabled = this._hasSelection || this._isGrabbing;
      this.outlinerCamera.gameObject.SetActive(this.drawOutlinePostProcessing.enabled);
    }
  }

  public bool isGrabbing
  {
    get => this._isGrabbing;
    set
    {
      this._isGrabbing = value;
      this.mouseLook1.IsGrabbingObject = value;
      this.mouseLook2.IsGrabbingObject = value;
      this.drawOutlinePostProcessing.enabled = this._hasSelection || this._isGrabbing;
      this.outlinerCamera.gameObject.SetActive(this.drawOutlinePostProcessing.enabled);
    }
  }

  public GameObject GetGrabbedObject() => this.grabbedObject;

  private Quaternion _GetCurrentObjectRotationWorldSpace()
  {
    Quaternion quaternion = this.transform.localToWorldMatrix.rotation * this._GetCurrentObjectRotationCameraSpace();
    DreamObjectDropTriggerScript component = this.grabbedObject.GetComponent<DreamObjectDropTriggerScript>();
    if (!(bool) (UnityEngine.Object) component)
      return quaternion;
    component.ShouldSnap(out float _);
    return quaternion;
  }

  private Quaternion _GetCurrentObjectRotationCameraSpace()
  {
    Quaternion quaternion = this.grabbedObjectRotationInCameraSpaceOriginal;
    DropTriggerScript component1 = this.grabbedObject.GetComponent<DropTriggerScript>();
    DreamObjectDropTriggerScript component2 = this.grabbedObject.GetComponent<DreamObjectDropTriggerScript>();
    if ((bool) (UnityEngine.Object) component2 && component2.FreezeRotation)
      quaternion = this.transform.worldToLocalMatrix.rotation * this.grabbedObjectRotationInWorldSpaceOriginal;
    if (!component1.grabValues.selfRightingLock)
      return quaternion;
    Vector3 vector3_1 = Vector3.up;
    if (component1.optionalSelfRightingLocalUpVector != Vector3.zero)
      vector3_1 = component1.optionalSelfRightingLocalUpVector;
    Vector3 vector3_2 = this.transform.worldToLocalMatrix.rotation * Vector3.up;
    Vector3 fromDirection = quaternion * vector3_1;
    Quaternion b = Quaternion.FromToRotation(Vector3.up, vector3_2) * Quaternion.FromToRotation(fromDirection, Vector3.up);
    if (this.isLerpingToPosition)
      b = Quaternion.Slerp(Quaternion.identity, b, this._GetLerpProgress());
    return Quaternion.AngleAxis(this.accumulatedPlayerRotationCameraSpaceSelfRightingLock.y, vector3_2) * b * quaternion;
  }

  private float _GetMinGrabDistance() => GameManager.GM.player.transform.localScale.x * 0.25f;

  public void OverrideOutlineColor(Color? overrideColor)
  {
    this.outlineOverrideColor = overrideColor;
    if (!this.outlineOverrideColor.HasValue)
      return;
    this.DrawOutlineMat.color = this.outlineOverrideColor.Value;
  }

  private void Start()
  {
    MultiplayerMode component = GameManager.GM.GetComponent<MultiplayerMode>();
    this.hasGrabRestrictions = PhotonNetwork.IsConnected && component.MultiplayerType == MultiplayerType.BattleRoyale;
    this.isCampaign = PhotonNetwork.IsConnected && (bool) (UnityEngine.Object) component.LevelInfo && component.LevelInfo.LevelProfile.IsCampaign;
    this.keyTracker = new KeystrokeTracker()
    {
      KeyCodes = new KeyCode[3]
      {
        KeyCode.R,
        KeyCode.T,
        KeyCode.Y
      }
    };
    this.fadeMaterialPool = new MaterialPool(new CustomizeMaterial(this.MakeMaterialFade));
    if ((bool) (UnityEngine.Object) this.drawOutlinePostProcessing)
    {
      this.DrawOutlineMat = this.drawOutlinePostProcessing.mat;
      this.DrawOutlineMat.color = this.canSpinColor;
    }
    this._layerMaskIgnoreGrabbed = ~(1 << MoSTLayer.IgnoreRaycast | 1 << MoSTLayer.Grabbed | 1 << MoSTLayer.Player | 1 << MoSTLayer.IgnoreRaycastAndObjects | 1 << MoSTLayer.NoInteraction);
    this._layerMaskGrabbed = 1 << MoSTLayer.Grabbed;
    this._layerMaskIgnorePlayer = ~(1 << MoSTLayer.Player | 1 << MoSTLayer.IgnoreRaycast | 1 << MoSTLayer.IgnoreRaycastAndObjects);
    this._layerMaskOnlyPlayer = 1 << MoSTLayer.Player;
    MouseLook[] componentsInChildren = this.transform.root.GetComponentsInChildren<MouseLook>();
    if (componentsInChildren.Length >= 1)
      this.mouseLook1 = componentsInChildren[0];
    if (componentsInChildren.Length >= 2)
      this.mouseLook2 = componentsInChildren[1];
    this.repeatInstantProjectCount = this.repeatInstantProjectMax;
    this._ChallengeMode = GameManager.GM.GetComponent<ChallengeMode>();
    this._MiniChallengeMode = GameManager.GM.GetComponent<MiniChallengeMode>();
    if (!PhotonNetwork.IsConnected || !MultiplayerHelper.IsMine(this.gameObject))
      return;
    PhotonNetwork.AddCallbackTarget((object) this);
  }

  private bool _MultiplayerImGrabbed()
  {
    PhotonView component = this.transform.parent.GetComponent<PhotonView>();
    return (bool) (UnityEngine.Object) component && PhotonNetwork.IsConnected && !component.IsMine;
  }

  private bool _StillWaitingToGrab(DropTriggerScript dts) => (bool) (UnityEngine.Object) this.MultiplayerGrabSettings && dts.TimeSinceSomeoneElseGrabbed.HasValue;

  private bool _IsGrabRestricted(GameObject hoverObject)
  {
    DropTriggerScript component = hoverObject.GetComponent<DropTriggerScript>();
    return (bool) (UnityEngine.Object) this.MultiplayerGrabSettings && this.hasGrabRestrictions && ((bool) (UnityEngine.Object) component.TimedGrabSettings && (bool) (UnityEngine.Object) component) && !component.grabValues.isCloneable;
  }

  public void SetHoverTimeModifier(float modifier, float duration)
  {
    this.hoverTimeModifier = modifier;
    this.hoverTimeModifierDuration = duration;
  }

  private void _ClearHoverTimeModifier()
  {
    this.hoverTimeModifierDuration = 0.0f;
    this.hoverTimeModifier = 1f;
  }

  private void _UpdateHoverTimeModifier()
  {
    if (this._MultiplayerImGrabbed())
      this.SetHoverTimeModifier(this.MultiplayerGrabSettings.IGotGrabbedHoverTimeBoost, this.MultiplayerGrabSettings.DurationHoverTimeBoost);
    if ((double) this.hoverTimeModifierDuration <= 0.0)
      return;
    this.hoverTimeModifierDuration -= Time.deltaTime;
    if ((double) this.hoverTimeModifierDuration > 0.0)
      return;
    this._ClearHoverTimeModifier();
  }

  private bool _GrabCountdownHasPassed()
  {
    if ((bool) (UnityEngine.Object) this.lastHoverObject)
    {
      DropTriggerScript component = this.lastHoverObject.GetComponent<DropTriggerScript>();
      if ((bool) (UnityEngine.Object) component && (bool) (UnityEngine.Object) component.TimedGrabSettings && !component.grabValues.isCloneable)
        return component.TimeGrabCanGrab(this.hoverTimeModifier);
    }
    return true;
  }

  private void _UpdateWaitingToGrabCountdown(GameObject hoverObject, float deltaTime)
  {
    if (this._MultiplayerImGrabbed())
      hoverObject = (GameObject) null;
    this._SetLastHoverObject(!this.isGrabbing ? hoverObject : (GameObject) null);
  }

  private void _SetLastHoverObject(GameObject hoverObject)
  {
    if (!((UnityEngine.Object) hoverObject != (UnityEngine.Object) this.lastHoverObject))
      return;
    if ((bool) (UnityEngine.Object) this.lastHoverObject)
      this.lastHoverObject.GetComponent<DropTriggerScript>().IsHovered = false;
    this.lastHoverObject = hoverObject;
    if (!(bool) (UnityEngine.Object) this.lastHoverObject)
      return;
    this.lastHoverObject.GetComponent<DropTriggerScript>().IsHovered = true;
  }

  public float? GetPercentWaitingToGrab()
  {
    if ((bool) (UnityEngine.Object) this.lastHoverObject)
    {
      DropTriggerScript component = this.lastHoverObject.GetComponent<DropTriggerScript>();
      if ((bool) (UnityEngine.Object) component && (bool) (UnityEngine.Object) component.TimedGrabSettings && !component.grabValues.isCloneable)
        return new float?(component.GetHoverGrabProgress() / this.hoverTimeModifier);
    }
    return new float?();
  }

  private bool _InGrabRecovery(GameObject aboutToGrab) => !this.isGrabbing && (double) this.grabRecoveryCountdown > 0.0 && this._IsGrabRestricted(aboutToGrab);

  private void _UpdateGrabRecovery()
  {
    if (!(bool) (UnityEngine.Object) this.MultiplayerGrabSettings)
      return;
    if (this.isGrabbing && (bool) (UnityEngine.Object) this.grabbedObject && this._IsGrabRestricted(this.grabbedObject))
    {
      this.grabRecoveryTime = this.MultiplayerGrabSettings.PostGrabRecovery;
      this.grabRecoveryCountdown = this.grabRecoveryTime;
    }
    else
    {
      double recoveryCountdown = (double) this.grabRecoveryCountdown;
      this.grabRecoveryCountdown -= Time.deltaTime;
      if (recoveryCountdown <= 0.0 || (double) this.grabRecoveryCountdown > 0.0)
        return;
      this._SetLastHoverObject((GameObject) null);
    }
  }

  public float? GetShouldShowGrabRecoveryProgress() => !this.isGrabbing && (bool) (UnityEngine.Object) this.lastHoverObject && (this._IsGrabRestricted(this.lastHoverObject) && (double) this.grabRecoveryCountdown > 0.0) ? new float?(this.grabRecoveryCountdown / this.grabRecoveryTime) : new float?();

  public float? GetForceLetGoProgress() => (double) this.forceLetGoTime > 0.0 ? new float?(this.forceLetGoCountdown / this.forceLetGoTime) : new float?();

  private bool _ForcedToDrop() => (double) this.forceLetGoTime > 0.0 && (double) this.forceLetGoCountdown <= 0.0;

  private void _UpdateForceLetGo(float deltaTime)
  {
    if ((bool) (UnityEngine.Object) this.grabbedObject && this.isGrabbing)
    {
      if ((UnityEngine.Object) this.grabbedObject == (UnityEngine.Object) this.lastGrabbedObject)
      {
        this.forceLetGoCountdown = Mathf.Max(0.0f, this.forceLetGoCountdown - deltaTime);
      }
      else
      {
        this.forceLetGoTime = 0.0f;
        if (this._IsGrabRestricted(this.grabbedObject))
          this.forceLetGoTime = this.grabbedObject.GetComponent<DropTriggerScript>().TimedGrabSettings.MaxGrabTime;
        this.forceLetGoCountdown = this.forceLetGoTime;
      }
    }
    else
    {
      this.forceLetGoTime = 0.0f;
      this.forceLetGoCountdown = 0.0f;
    }
    this.lastGrabbedObject = this.isGrabbing ? this.grabbedObject : (GameObject) null;
  }

  private void Update()
  {
    this._UpdateGrabRecovery();
    this._UpdateHoverTimeModifier();
    if (this.keyTracker.Check())
      this.RayCastType = (GrabObjectRayCastType) ((int) (this.RayCastType + 1) % 3);
    if (!GameManager.GM.PM.canControl)
      return;
    if (this.isGrabbing && !(bool) (UnityEngine.Object) this.grabbedObject)
      this.isGrabbing = false;
    this._UpdateGrabSizeStuffWhenGrabbing();
    this._UpdateForceLetGo(Time.deltaTime);
    this.isReadyToGrab = false;
    this.isObjectBlocked = false;
    this.isRejectProject = false;
    this.isObjectReadyToReturn = false;
    this.justDroppedThisFrame = false;
    if ((bool) (UnityEngine.Object) this.mouseLook1)
      this.mouseLook1.skipUpdate = false;
    if ((bool) (UnityEngine.Object) this.mouseLook2)
      this.mouseLook2.skipUpdate = false;
    bool supressDeniedSound = false;
    bool shouldScroll = false;
    Portal crossedPortal = (Portal) null;
    if (!this.isGrabbing && !this.isScrolling)
    {
      this.grabbedObject = (GameObject) null;
      this.isReadyToGrab = false;
      if (this.AllowScrollPlacement)
        GameManager.GM.guiCamera.GetComponent<DrawCursorScriptHand>().TurnOffPointLeftAndRightAndUpAndDownGUI();
      GameObject firstGrabbableObject = this.getFirstGrabbableObject(out crossedPortal, out supressDeniedSound);
      if ((UnityEngine.Object) firstGrabbableObject != (UnityEngine.Object) null)
      {
        DropTriggerScript component1 = firstGrabbableObject.GetComponent<DropTriggerScript>();
        if ((bool) (UnityEngine.Object) component1)
        {
          this.isPointingAtInstantProjectObj = component1.grabValues.instantProject;
          this.grabbedObject = firstGrabbableObject;
          DreamObjectDropTriggerScript component2 = component1.GetComponent<DreamObjectDropTriggerScript>();
          if (this.AllowScrollPlacement && (bool) (UnityEngine.Object) component2 && component2.CanUseScrollPlacement())
          {
            if (this.ShouldUseVerticalHandCursor(firstGrabbableObject))
              GameManager.GM.guiCamera.GetComponent<DrawCursorScriptHand>().DrawPointLeftAndRightGUI();
            else
              GameManager.GM.guiCamera.GetComponent<DrawCursorScriptHand>().DrawPointUpAndDownGUI();
            shouldScroll = true;
          }
          else
            this.isReadyToGrab = true;
          if (this.grabbedObject.GetComponent<DropTriggerScript>().toReturn)
            this.isObjectReadyToReturn = true;
        }
      }
      else if (ReInput.isReady && ReInput.controllers.GetLastActiveController().type == ControllerType.Joystick)
      {
        GameObject hitObject;
        if (ResizeScript._CastSphereForObject(new Ray(this.transform.position, this.transform.forward), this.AssistCastRadius, this.AssistCastDistance, this._layerMaskIgnorePlayer, out hitObject, out GameObject _))
        {
          this.mouseLook1.IsNearGrabbableObject = true;
          this.mouseLook2.IsNearGrabbableObject = true;
          this.mouseLook1.NearbyGrabbleObject = hitObject;
          this.mouseLook2.NearbyGrabbleObject = hitObject;
        }
        else
        {
          this.mouseLook1.IsNearGrabbableObject = false;
          this.mouseLook2.IsNearGrabbableObject = false;
          this.mouseLook1.NearbyGrabbleObject = (GameObject) null;
          this.mouseLook2.NearbyGrabbleObject = (GameObject) null;
        }
      }
    }
    this._UpdateWaitingToGrabCountdown(this.grabbedObject, Time.deltaTime);
    if ((bool) (UnityEngine.Object) this.grabbedObject && (this.notAllowedToGrab || this._MultiplayerImGrabbed() || (this._InGrabRecovery(this.grabbedObject) || this._StillWaitingToGrab(this.grabbedObject.GetComponent<DropTriggerScript>()))))
    {
      if (this.isGrabbing)
        this.DoDropDownObject();
      if (this.isScrolling)
        this.EndScrolling();
      this.grabbedObject = (GameObject) null;
      this.isReadyToGrab = false;
      shouldScroll = false;
    }
    if (!(bool) (UnityEngine.Object) this.grabbedObject)
    {
      if (!GameManager.GM.playerInput.GetButtonDown("Grab") || this.isGrabbing || (!(bool) (UnityEngine.Object) this.soundEffectScript || supressDeniedSound) || this.turnOffGrabDeniedSoundNextFrame)
        return;
      this.soundEffectScript.play_denied_sound();
    }
    else
    {
      if (!this._GrabCountdownHasPassed())
        return;
      if (this.isLerpingToPosition)
      {
        if ((UnityEngine.Object) this.grabbedObject == (UnityEngine.Object) null || !this.isGrabbing)
          this.isLerpingToPosition = false;
        else if ((double) this.curLerpingTime < 0.800000011920929)
        {
          this.toResizeWithoutDropping = true;
          this.curLerpingTime += Time.deltaTime;
        }
        else
        {
          this.isLerpingToPosition = false;
          this.toResizeWithoutDropping = true;
        }
      }
      this.grabbedObject.GetComponent<DreamObjectDropTriggerScript>();
      if (GameManager.GM.playerInput.GetButtonDown("Grab") && !this.isGrabbing && !this.isScrolling || this.grabbedObject.GetComponent<DropTriggerScript>().doesRepeatInstantProject && this.repeatInstantProjectCount < this.repeatInstantProjectMax)
      {
        DropTriggerScript component = this.grabbedObject.GetComponent<DropTriggerScript>();
        if (component.toReturn)
        {
          if (!GameManager.GM.TM.isFmodTest)
            this.soundEffectScript.play_return_sound();
          else
            this.soundEffectScript.play_fmod_return_sound(this.grabbedObject.transform);
          component.ReturnOriginal();
        }
        else if (component.IsCloneButTooManyClones())
        {
          if ((bool) (UnityEngine.Object) this.soundEffectScript)
            this.soundEffectScript.play_denied_sound();
        }
        else
        {
          if ((UnityEngine.Object) this.grabbedObject.GetComponent<ProjectThroughThisObjWhenCloning>() != (UnityEngine.Object) null)
            this.grabbedObject.GetComponent<BoxCollider>().enabled = false;
          if (!this.dontLerpObjectsToCenter && !shouldScroll)
          {
            this.isLerpingToPosition = true;
            this.curLerpingTime = 0.0f;
          }
          this.DoGrabObject(crossedPortal, shouldScroll);
          if (component.grabValues.instantProject)
          {
            this.DoDropDownObject();
            if (component.grabValues.instaBridge)
              this.CreateInstaBridge(crossedPortal);
            component.hasBeenInstantProjected = true;
            if (this.repeatInstantProjectCount < this.repeatInstantProjectMax)
              ++this.repeatInstantProjectCount;
          }
          else if ((UnityEngine.Object) this.grabbedObject != (UnityEngine.Object) null && this.isGrabbing)
            this.DoDynamicProjectObject();
          if ((UnityEngine.Object) this.grabbedObject.GetComponent<ProjectThroughThisObjWhenCloning>() != (UnityEngine.Object) null)
          {
            this.grabbedObject.GetComponent<BoxCollider>().enabled = true;
            component.grabValues.instantProject = false;
            component.grabValues.isCloneable = false;
            this.oldObj.GetComponent<BoxCollider>().enabled = true;
            UnityEngine.Object.Destroy((UnityEngine.Object) this.grabbedObject.GetComponent<ProjectThroughThisObjWhenCloning>());
          }
          if ((UnityEngine.Object) this.SpinInstruction != (UnityEngine.Object) null && component.grabValues.canSpin)
            this.spinGUIStartinPoint = (Vector3) this.GetBottomRightBoundingInScreenSpace(this.grabbedObject);
          if ((bool) (UnityEngine.Object) this.DropInstruction)
            this.dropGUIStartinPoint = (Vector3) this.GetBottomRightBoundingInScreenSpace(this.grabbedObject);
        }
      }
      else if (GameManager.GM.playerInput.GetButtonDown("Grab") && (this.isGrabbing || this.isScrolling))
      {
        if (this.isScrolling)
          this.EndScrolling();
        else
          this.DoDropDownObject();
      }
      else if (GameManager.GM.playerInput.GetButtonDown("Grab") && this.isGrabbing && this.grabbedObject.GetComponent<DropTriggerScript>().grabValues.canFollow)
        this.DoDropDownObject();
      else if (this.isGrabbing && this._ForcedToDrop())
        this.DoDropDownObject();
      else if (this.isGrabbing && this.grabbedObject.GetComponent<DropTriggerScript>().grabValues.canSpin)
      {
        if (GameManager.GM.playerInput.GetButton("Rotate"))
        {
          DreamObjectDropTriggerScript component = this.grabbedObject.GetComponent<DreamObjectDropTriggerScript>();
          if ((bool) (UnityEngine.Object) component && component.FreezeRotation)
          {
            this.SetRotationAsCurrent(this.grabbedObject.transform.rotation);
            component.FreezeRotation = false;
          }
          this.mouseLook1.skipUpdate = true;
          this.mouseLook2.skipUpdate = true;
          this.RotateObjectByLocalAxis();
        }
        if (GameManager.GM.playerInput.GetButtonDown("Rotate") && this.doRotateTutInThisLevel)
          this.StartHoldRotateTimer();
        this.toResizeWithoutDropping = true;
      }
      else if (this.isGrabbing && this.grabbedObject.GetComponent<DropTriggerScript>().grabValues.canFreeze)
      {
        if (GameManager.GM.playerInput.GetButton("Rotate"))
        {
          this.grabbedObject.layer = MoSTLayer.Default;
          this.grabbedObject.GetComponent<DropTriggerScript>().returnChildrenColliderLayers();
          this.SetRotationAsCurrent(this.grabbedObject.transform.rotation);
          this.toResizeWithoutDropping = false;
        }
        else
        {
          if (this.grabbedObject.layer != MoSTLayer.Grabbed)
          {
            this.grabbedObject.layer = MoSTLayer.Grabbed;
            this.grabbedObject.GetComponent<DropTriggerScript>().setChildrenColliderLayers(MoSTLayer.Grabbed);
          }
          this.toResizeWithoutDropping = true;
        }
      }
      else if (this.isGrabbing)
        this.toResizeWithoutDropping = true;
      else if (!this.isGrabbing && this.grabbedObject.GetComponent<DropTriggerScript>().grabValues.isCloneable && GameManager.GM.playerInput.GetButtonDown("Rotate"))
      {
        DropTriggerScript component = this.grabbedObject.GetComponent<DropTriggerScript>();
        if ((!((UnityEngine.Object) component.cloneChild == (UnityEngine.Object) null) || !((UnityEngine.Object) component.cloneParent == (UnityEngine.Object) null)) && !component.ObjectIsPerPlayer && (!this.IsMultiplayerPlayer || this.isCampaign))
        {
          this.soundEffectScript.play_clone_retrieve_sound();
          this.RetractClone(component);
        }
      }
      if ((double) this.holdRotateTutorialTimer > 0.0)
        this.holdRotateTutorialTimer -= Time.deltaTime;
      else if ((double) this.holdRotateTutorialTimer <= 0.0 && (double) this.holdRotateTutorialTimer > -1000.0)
      {
        if ((UnityEngine.Object) this.rotateTut != (UnityEngine.Object) null)
          this.rotateTut.enabled = false;
        this.holdRotateTutorialTimer = -1001f;
      }
      this.UpdateScrollThing();
    }
  }

  private void FixedUpdate()
  {
    this.notAllowedToGrab = false;
    this.turnOffGrabDeniedSoundNextFrame = false;
    if (this.notAllowedToGrabNextFrame)
      this.notAllowedToGrab = true;
    this.notAllowedToGrabNextFrame = false;
  }

  private void CreateInstaBridge(Portal crossedPortal)
  {
    for (int index = 0; index < this.grabbedObject.GetComponent<DropTriggerScript>().grabValues.clonesInBridge - 1; ++index)
    {
      this.DoGrabObject(crossedPortal, false);
      this.DoDropDownObject();
    }
  }

  private GrabResult ResizeWithoutDropping()
  {
    if (this.isEnableDebug)
      GameManager.GM.MyLog("Grab Distance:" + (object) this._GetMinGrabDistance() + ",");
    this.ResetObjectToMinDistance(this.grabbedObject, 1f);
    DropTriggerScript component = this.grabbedObject.GetComponent<DropTriggerScript>();
    if (component.grabValues.isAlwaysSameScale)
    {
      this.grabbedObject.transform.localScale *= Mathf.Lerp(1f, component.optionalAlwaysScaleX / this.grabbedObject.transform.lossyScale.x, 0.1f);
      component.UpdateMassBasedOnScale();
    }
    GrabResult grabResult = this.DoDynamicProjectObject();
    if (component.grabValues.hasMaxSize)
    {
      float x = this.grabbedObject.transform.lossyScale.x;
      float optionalMaxScaleX = component.optionalMaxScaleX;
      if ((double) x > (double) optionalMaxScaleX)
        this.grabbedObject.transform.localScale *= optionalMaxScaleX / x;
    }
    if (this.isRejectProject)
    {
      this.isObjectBlocked = true;
      component.setSelfAndChildrenMaterials(this.blockedMat);
    }
    else
      component.returnSelfAndChildrenRenderMaterials();
    this.lastCrossedPortal = grabResult.CrossedPortal;
    if (component.OnGrabbing != null)
      component.OnGrabbing.Invoke();
    if (this.immediatelyDropObjects)
      this.DoDropDownObject();
    return grabResult;
  }

  public bool ProjectedThroughPortal() => (UnityEngine.Object) this.lastCrossedPortal != (UnityEngine.Object) null;

  private GrabResult DoDynamicProjectObject()
  {
    Portal crossedPortal;
    float reductionRatio;
    float distance = this.getResizeDistance(this.grabbedObject, out crossedPortal, out reductionRatio);
    if ((double) distance == 3.40282346638529E+38)
      distance = this._maxGrabDistance;
    if ((double) distance == 3.40282346638529E+38)
    {
      if (this.isEnableDebug)
        GameManager.GM.MyLog("Edge case!");
    }
    else if ((double) distance > 0.0)
    {
      this._EnsureObjectDetached();
      this.UpdateObjectTransformAndPropertyByDistance(this.grabbedObject, distance, crossedPortal, reductionRatio);
      this.DrawIndicatorIfObjectTooSmall(reductionRatio);
      if (this.isEnableDebug)
        GameManager.GM.MyLog("resize dist: " + (object) distance);
    }
    else
      GameManager.GM.MyLog("Return value of resize ratio is <= 0");
    return new GrabResult()
    {
      CrossedPortal = crossedPortal
    };
  }

  private void OnDestroy()
  {
    if (this.rayCastCommands.IsCreated)
      this.rayCastCommands.Dispose();
    if (this.rayCastResults.IsCreated)
      this.rayCastResults.Dispose();
    if (this.rayCastCommandsPortal.IsCreated)
      this.rayCastCommandsPortal.Dispose();
    if (this.rayCastResultsPortal.IsCreated)
      this.rayCastResultsPortal.Dispose();
    if (this.filteredRayIndices.IsCreated)
      this.filteredRayIndices.Dispose();
    if (this.fadeMaterialPool == null)
      return;
    this.fadeMaterialPool.Destroy();
    this.fadeMaterialPool = (MaterialPool) null;
  }

  private void MakeMaterialFade(Material material)
  {
    material.SetInt("_SrcBlend", 5);
    material.SetInt("_DstBlend", 10);
    material.SetInt("_ZWrite", 0);
    material.DisableKeyword("_ALPHATEST_ON");
    material.EnableKeyword("_ALPHABLEND_ON");
    material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
    material.renderQueue = 3000;
    material.SetOverrideTag("RenderType", "Fade");
    if (!material.HasProperty("_Color"))
      return;
    Color color = material.color;
    color.a *= 0.5f;
    material.color = color;
  }

  private void DrawIndicatorIfObjectTooSmall(float reductionRatio)
  {
    bool flag = false;
    float num = 1f;
    float objectTooSmallAmount = this.GetGrabbedObjectTooSmallAmount();
    if ((double) objectTooSmallAmount < 1.0)
    {
      num = 1f / objectTooSmallAmount;
      flag = true;
    }
    if ((double) reductionRatio < 1.0)
    {
      num = 1f / reductionRatio;
      flag = true;
    }
    if (!flag || this.fadeMaterialPool == null)
      return;
    FakeObjectModifiers modifiers = new FakeObjectModifiers()
    {
      ShadowCastingMode = new ShadowCastingMode?(ShadowCastingMode.Off)
    };
    this.fadeMaterialPool.FrameReset();
    DrawFakeObjectHelper.DrawGameObject(this.grabbedObject, GameManager.GM.playerCamera, new Vector3(num, num, num), this.fadeMaterialPool, ref modifiers);
  }

  private void EnlargenIfTooSmall()
  {
    float objectTooSmallAmount = this.GetGrabbedObjectTooSmallAmount();
    if ((double) objectTooSmallAmount >= 1.0)
      return;
    this.grabbedObject.transform.localScale *= 1f / objectTooSmallAmount;
  }

  private float GetGrabbedObjectTooSmallAmount()
  {
    float minimumSize = this.grabbedObject.GetComponent<DropTriggerScript>().grabValues.MinimumSize;
    Mesh mesh = this.GetMesh(this.grabbedObject);
    Vector3 a;
    if ((bool) (UnityEngine.Object) mesh)
    {
      a = mesh.bounds.size;
    }
    else
    {
      ReducedMeshForRayCasting component = this.grabbedObject.GetComponent<ReducedMeshForRayCasting>();
      a = !(bool) (UnityEngine.Object) component ? new Vector3() : component.GetLocalBoundsSize();
    }
    Vector3 vector3 = Vector3.Scale(a, this.grabbedObject.transform.lossyScale);
    return Mathf.Max(0.0001f, Mathf.Max(vector3.x / minimumSize, Mathf.Max(vector3.y / minimumSize, vector3.z / minimumSize)));
  }

  private void SetRotationAsCurrent(Quaternion grabbedObjectRotation)
  {
    this.grabbedObjectRotationInCameraSpaceOriginal = this.transform.worldToLocalMatrix.rotation * grabbedObjectRotation;
    this.accumulatedPlayerRotationCameraSpaceSelfRightingLock = Vector3.zero;
    this.grabbedObjectRotationInWorldSpaceOriginal = grabbedObjectRotation;
  }

  private void SetPositionAsOriginal(
    Vector3 worldPosition,
    Portal crossedPortal,
    DropTriggerScript dts)
  {
    if ((bool) (UnityEngine.Object) crossedPortal && (bool) (UnityEngine.Object) crossedPortal.Destination)
      worldPosition = PortalHelper.TransformPointRelativeToPortal(crossedPortal.Destination, crossedPortal, worldPosition);
    this.positionInCameraSpaceOriginal = this.transform.InverseTransformPoint(worldPosition);
    Vector3 cameraSpaceOriginal = this.positionInCameraSpaceOriginal;
    float t = dts.grabValues.AnchorWhereGrabbed;
    DreamObjectDropTriggerScript component = dts.GetComponent<DreamObjectDropTriggerScript>();
    if ((bool) (UnityEngine.Object) component && component.ShouldAnchorToGrabPoint())
      t = 1f;
    else
      cameraSpaceOriginal.x = 0.0f;
    this.positionInCameraSpaceOriginalFinal = Vector3.Slerp(Vector3.forward, cameraSpaceOriginal, t);
  }

  private void LateUpdate()
  {
    this.continueInLateLateUpdate = false;
    if (this.RayCastType == GrabObjectRayCastType.MultiThreadDeferred)
    {
      this._UpdateGrabSizeStuffWhenGrabbing();
      if (!this.isGrabbing)
        return;
      this.ResetObjectToMinDistance(this.grabbedObject, 1f);
      DropTriggerScript component = this.grabbedObject.GetComponent<DropTriggerScript>();
      if (component.grabValues.isAlwaysSameScale)
      {
        this.grabbedObject.transform.localScale *= Mathf.Lerp(1f, component.optionalAlwaysScaleX / this.grabbedObject.transform.lossyScale.x, 0.1f);
        component.UpdateMassBasedOnScale();
      }
      this.getResizeDistanceWorker_Parallel2(this.grabbedObject, 1f);
      this.continueInLateLateUpdate = true;
    }
    else
      this._LateUpdateWorker();
  }

  private void _MaybeSnap(GameObject theObject, bool justDraw)
  {
    DreamObjectDropTriggerScript component = theObject.GetComponent<DreamObjectDropTriggerScript>();
    if (!(bool) (UnityEngine.Object) component || !component.ShouldBeMagnetic())
      return;
    this.snapWorker.Clear();
    SmartSnapHelper.Snap(GameManager.GM.GetComponent<DreamManagerProxy>().DreamManager, (IEnumerable<DreamObjectDefinition>) new DreamObjectDefinition[1]
    {
      theObject.GetComponent<DreamObjectDefinition>()
    }, true, this.snapWorker);
    if (!this.snapWorker[0].Snapped)
      return;
    if (justDraw)
    {
      if (this.fadeMaterialPool == null)
        return;
      FakeObjectModifiers modifiers = new FakeObjectModifiers()
      {
        ShadowCastingMode = new ShadowCastingMode?(ShadowCastingMode.Off),
        Material = this.SnapMaterial
      };
      Matrix4x4 preMatrix = Matrix4x4.TRS(this.snapWorker[0].Position, this.snapWorker[0].Rotation, this.snapWorker[0].LocalScale) * theObject.transform.worldToLocalMatrix;
      DrawFakeObjectHelper.DrawGameObject2(theObject, GameManager.GM.playerCamera, preMatrix, ref modifiers);
    }
    else
      this.snapWorker[0].Apply();
  }

  private void _LateUpdateWorker()
  {
    GrabResult grabResult = new GrabResult();
    this._UpdateGrabSizeStuffWhenGrabbing();
    if (this.isGrabbing && (bool) (UnityEngine.Object) this.grabbedObject)
    {
      this.prevPosition = this.grabbedObject.transform.position;
      if (this.toResizeWithoutDropping)
        grabResult = this.ResizeWithoutDropping();
      this._MaybeSnap(this.grabbedObject, true);
    }
    this.toResizeWithoutDropping = false;
    if (!(bool) (UnityEngine.Object) this.outlinerCamera)
      return;
    if ((bool) (UnityEngine.Object) this.grabbedObject && this.isGrabbing && (bool) (UnityEngine.Object) grabResult.CrossedPortal)
    {
      PortalHelper.PositionObjectRelativeToPortal(grabResult.CrossedPortal, GameManager.GM.playerCamera.transform, this.outlinerCamera.transform);
    }
    else
    {
      this.outlinerCamera.transform.localPosition = Vector3.zero;
      this.outlinerCamera.transform.localRotation = Quaternion.identity;
      this.outlinerCamera.transform.localScale = Vector3.one;
    }
  }

  public void LateLateUpdate()
  {
    if (!this.continueInLateLateUpdate || this.RayCastType != GrabObjectRayCastType.MultiThreadDeferred)
      return;
    this._LateUpdateWorker();
  }

  private void OnGUI()
  {
    if (!((UnityEngine.Object) this.SpinInstruction != (UnityEngine.Object) null) || !this.isGrabbing || !this.grabbedObject.GetComponent<DropTriggerScript>().grabValues.canSpin)
      return;
    Vector2 vector2 = new Vector2((float) Screen.width * 0.07f, (float) Screen.width * 0.07f);
    GUI.DrawTexture(new Rect(this.spinGUIStartinPoint.x, this.spinGUIStartinPoint.y, vector2.x, vector2.y), this.SpinInstruction);
  }

  private Vector2 GetBottomRightBoundingInScreenSpace(GameObject targetObject)
  {
    Vector3 center = targetObject.GetComponent<Collider>().bounds.center;
    Vector3 vector3 = this.transform.right.normalized * targetObject.GetComponent<Collider>().bounds.extents.magnitude;
    if (this.isEnableDebug)
      UnityEngine.Debug.DrawLine(center, center + vector3, Color.cyan);
    Vector3 position = center + vector3 * 0.5f;
    return (Vector2) this.GetComponent<Camera>().WorldToScreenPoint(position);
  }

  private void RotateObjectByLocalAxis()
  {
    float f = GameManager.GM.playerInput.GetAxis("Look Horizontal") * InvertAxis.GetInvertXAxisMultiplier();
    float num = GameManager.GM.playerInput.GetAxis("Look Vertical") * InvertAxis.GetInvertYAxisMultiplier();
    Vector3 direction;
    if (this.grabbedObject.GetComponent<DropTriggerScript>().optionalSpinYAxisOnly)
    {
      direction = new Vector3(0.0f, -f, 0.0f) * (Time.deltaTime * 150f);
    }
    else
    {
      direction = (double) Mathf.Abs(num) <= (double) Mathf.Abs(f) * 3.0 ? ((double) Mathf.Abs(num) * 3.0 >= (double) Mathf.Abs(f) ? new Vector3(num, -f, 0.0f) * 1f : new Vector3(0.0f, -f, 0.0f)) : new Vector3(num, 0.0f, 0.0f);
      direction = this.transform.TransformDirection(direction);
      direction *= Time.deltaTime * 100f;
    }
    this.accumulatedPlayerRotationCameraSpaceSelfRightingLock += direction;
    if (this.grabbedObject.GetComponent<DropTriggerScript>().grabValues.selfRightingLock)
      return;
    Vector3 axis = this.transform.worldToLocalMatrix.rotation * Vector3.up;
    this.grabbedObjectRotationInCameraSpaceOriginal = Quaternion.AngleAxis(direction.y, axis) * this.grabbedObjectRotationInCameraSpaceOriginal;
  }

  public void RetractClone(DropTriggerScript dts)
  {
    this._RetractClone(dts, false);
    if (!(bool) (UnityEngine.Object) dts || !this.IsMultiplayerPlayer || !PhotonNetwork.IsConnected)
      return;
    PhotonView component = dts.GetComponent<PhotonView>();
    if (!(bool) (UnityEngine.Object) component)
      return;
    component.RPC("PhotonRetractClones", RpcTarget.Others);
  }

  public void RetractCloneRemote(DropTriggerScript dts) => this._RetractClone(dts, true);

  private void _RetractClone(DropTriggerScript dts, bool remotePlayerIsRetracting)
  {
    if (dts.isCloneRetracting)
      return;
    if (!remotePlayerIsRetracting && PhotonNetwork.IsConnected && (this.IsMultiplayerPlayer && (UnityEngine.Object) dts.cloneRoot != (UnityEngine.Object) dts))
      dts.TransferOwnershipToMe();
    if ((UnityEngine.Object) dts.cloneParent != (UnityEngine.Object) null)
    {
      this.StartCoroutine(this.LerpCloneToParent(dts, remotePlayerIsRetracting));
      dts.isCloneRetracting = true;
    }
    if ((UnityEngine.Object) dts.cloneChild != (UnityEngine.Object) null)
      this._RetractClone(dts.cloneChild, remotePlayerIsRetracting);
    if (!((UnityEngine.Object) dts.cloneParent != (UnityEngine.Object) null))
      return;
    this._RetractClone(dts.cloneParent, remotePlayerIsRetracting);
  }

  private IEnumerator LerpCloneToParent(
    DropTriggerScript dts,
    bool remotePlayerIsRetracting)
  {
    foreach (Collider componentsInChild in dts.GetComponentsInChildren<Collider>())
      componentsInChild.enabled = false;
    dts.ResetCollisionDetection();
    dts.SetIsKinematic(true);
    Transform myTransform = dts.transform;
    float maxLerpTime = 0.7f;
    float currentLerpTime = 0.0f;
    Vector3 initialPosition = myTransform.position;
    Vector3 initialScale = myTransform.localScale;
    Quaternion initialRotation = myTransform.rotation;
    while ((double) currentLerpTime < (double) maxLerpTime)
    {
      currentLerpTime += Time.deltaTime;
      float t = Mathf.Pow(currentLerpTime / maxLerpTime, 1.3f);
      if ((bool) (UnityEngine.Object) dts)
      {
        Transform transform = dts.cloneParent.transform;
        myTransform.position = Vector3.Lerp(initialPosition, transform.position, t);
        myTransform.localScale = Vector3.Lerp(initialScale, transform.localScale, t);
        myTransform.rotation = Quaternion.Lerp(initialRotation, transform.rotation, t);
      }
      yield return (object) new WaitForEndOfFrame();
    }
    if ((bool) (UnityEngine.Object) dts)
      dts.gameObject.SetActive(false);
    yield return (object) new WaitForSeconds(1f);
    if ((bool) (UnityEngine.Object) dts)
    {
      if (this.IsMultiplayerPlayer && PhotonNetwork.IsConnected)
      {
        if (!remotePlayerIsRetracting)
          PhotonNetwork.Destroy(dts.gameObject);
      }
      else
        UnityEngine.Object.Destroy((UnityEngine.Object) dts.gameObject);
    }
    yield return (object) null;
  }

  private void _EnsureObjectDetached()
  {
    if (!((UnityEngine.Object) this.grabbedObject.transform.root != (UnityEngine.Object) this.grabbedObject.transform))
      return;
    this.grabbedObject.transform.parent = (Transform) null;
  }

  private void _MaybeClaimThisPerPlayerObject(DropTriggerScript dts)
  {
    if (!dts.ObjectIsPerPlayer || !PhotonNetwork.IsConnected)
      return;
    dts.PerPlayerActorNumber = PhotonNetwork.LocalPlayer.ActorNumber;
  }

  private bool _ImTheLastPlayerToGrabObject(DropTriggerScript dtsIn)
  {
    int length = GameManager.GM.GetComponent<MultiplayerMode>().GetPlayersInCurrentRoom().Length;
    int num = 0;
    for (DropTriggerScript dropTriggerScript = dtsIn.cloneRoot; (bool) (UnityEngine.Object) dropTriggerScript; dropTriggerScript = dropTriggerScript.cloneChild)
    {
      if (dropTriggerScript.PerPlayerActorNumber != -1)
        ++num;
    }
    return num >= length - 1;
  }

  private bool _HaveIGrabbedThisObjectYet(DropTriggerScript dtsIn)
  {
    int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber;
    for (DropTriggerScript dropTriggerScript = dtsIn.cloneRoot; (bool) (UnityEngine.Object) dropTriggerScript; dropTriggerScript = dropTriggerScript.cloneChild)
    {
      if (dropTriggerScript.PerPlayerActorNumber == actorNumber)
        return true;
    }
    return false;
  }

  private bool _IsPerPlayerMPObjectAndIHaventGrabbedItYet(DropTriggerScript dts) => dts.ObjectIsPerPlayer && PhotonNetwork.IsConnected && !this._HaveIGrabbedThisObjectYet(dts) && !this._ImTheLastPlayerToGrabObject(dts);

  private void DoGrabObject(Portal crossedPortal, bool shouldScroll)
  {
    if (!(this.isReadyToGrab | shouldScroll))
      return;
    DropTriggerScript component1 = this.grabbedObject.GetComponent<DropTriggerScript>();
    DreamObjectDropTriggerScript component2 = this.grabbedObject.GetComponent<DreamObjectDropTriggerScript>();
    CloneOnce component3 = this.grabbedObject.GetComponent<CloneOnce>();
    bool flag1 = (bool) (UnityEngine.Object) component3 && component3.CloneMe;
    bool flag2 = (bool) (UnityEngine.Object) component2 && component2.ShouldClone();
    bool flag3 = this._IsPerPlayerMPObjectAndIHaventGrabbedItYet(component1);
    bool counterZFighting = false;
    if (component1.grabValues.isCloneable | flag2 | flag1 | flag3)
    {
      DropTriggerScript dtsParent = component1;
      component1.ResetCollisionDetection();
      counterZFighting = true;
      if ((UnityEngine.Object) this.grabbedObject.GetComponent<ProjectThroughThisObjWhenCloning>() == (UnityEngine.Object) null)
      {
        if (PhotonNetwork.IsConnected)
        {
          Vector3 localScale = this.grabbedObject.transform.localScale;
          this.grabbedObject = !(bool) (UnityEngine.Object) this.grabbedObject.GetComponent<MultiplayerPlayer>() ? PhotonNetwork.Instantiate(component1.cloneRoot.GetComponent<PhotonView>().sceneViewId.ToString(), this.grabbedObject.transform.position, this.grabbedObject.transform.rotation, data: MultiplayerHelper.CreateCloneInstanceData(this.grabbedObject)) : PhotonNetwork.Instantiate("Multiplayer/PlayerControllerPrefabMP", this.grabbedObject.transform.position, this.grabbedObject.transform.rotation, data: MultiplayerHelper.CreateCloneInstanceData(this.grabbedObject));
          this.grabbedObject.transform.localScale = localScale;
        }
        else
        {
          PhotonView component4 = this.grabbedObject.GetComponent<PhotonView>();
          if ((bool) (UnityEngine.Object) component4)
            component4.ViewID = 0;
          this.grabbedObject = UnityEngine.Object.Instantiate<GameObject>(this.grabbedObject, this.grabbedObject.transform.position, this.grabbedObject.transform.rotation);
          PhotonView component5 = this.grabbedObject.GetComponent<PhotonView>();
          if ((bool) (UnityEngine.Object) component5)
            component5.ViewID = 0;
        }
        component1 = this.grabbedObject.GetComponent<DropTriggerScript>();
        if (flag2)
        {
          this.grabbedObject.GetComponent<DreamObjectDropTriggerScript>().OnClone();
        }
        else
        {
          if (flag3)
            dtsParent.TurnOffGrabPermanentlyForMe();
          component1.InsertIntoCloneChain(dtsParent);
          HueModifier component4 = this.grabbedObject.GetComponent<HueModifier>();
          if ((bool) (UnityEngine.Object) component4)
            component4.Modify();
          if (component1.IsCloneButTooManyClones())
          {
            if ((bool) (UnityEngine.Object) this.CloneAlotAchievement)
              this.CloneAlotAchievement.Grant();
            if ((bool) (UnityEngine.Object) component4)
              component4.BonusMakeEmissive();
          }
        }
        if (this.OnCloneCreated != null)
          this.OnCloneCreated(this.grabbedObject);
      }
      else
      {
        GameObject theClone = UnityEngine.Object.Instantiate<GameObject>(this.grabbedObject, this.grabbedObject.transform.position, this.grabbedObject.transform.rotation);
        theClone.GetComponent<BoxCollider>().enabled = true;
        this.oldObj = this.grabbedObject;
        this.grabbedObject = theClone;
        component1 = this.grabbedObject.GetComponent<DropTriggerScript>();
        if (this.OnCloneCreated != null)
          this.OnCloneCreated(theClone);
      }
    }
    if (shouldScroll)
    {
      this.StartScrolling(counterZFighting);
    }
    else
    {
      this._MaybeClaimThisPerPlayerObject(component1);
      this.grabbedObject.layer = MoSTLayer.Grabbed;
      component1.setChildrenColliderLayers(MoSTLayer.Grabbed);
      Vector3 vector3_1 = this.grabbedObject.transform.position;
      this.SetPositionAsOriginal(vector3_1, crossedPortal, component1);
      if ((bool) (UnityEngine.Object) crossedPortal && (bool) (UnityEngine.Object) crossedPortal.Destination)
        vector3_1 = PortalHelper.TransformPointRelativeToPortal(crossedPortal.Destination, crossedPortal, vector3_1);
      Vector3 vector3_2 = vector3_1 - this.transform.position;
      float initialRatio = this._GetMinGrabDistance() / vector3_2.magnitude;
      if ((bool) (UnityEngine.Object) this.soundEffectScript)
        this.soundEffectScript.play_pop_sound_grab(component1.SizeEstimate());
      if (!this.isGrabbing)
        component1.SpawnGrabParticle();
      this._EnsureObjectDetached();
      this.SetScaleAtMinDistance(this.grabbedObject, initialRatio, crossedPortal);
      Quaternion quaternion = this.grabbedObject.transform.rotation;
      if ((bool) (UnityEngine.Object) crossedPortal && (bool) (UnityEngine.Object) crossedPortal.Destination)
        quaternion = PortalHelper.TransformRotation(crossedPortal.Destination, quaternion);
      this.SetRotationAsCurrent(quaternion);
      if (PhotonNetwork.IsConnected && this.IsMultiplayerPlayer)
        component1.TransferOwnershipToMe();
      if ((bool) (UnityEngine.Object) component1.TimedGrabSettings)
        this._ClearHoverTimeModifier();
      if (component1.OnGrabbedLocalPre != null)
        component1.OnGrabbedLocalPre.Invoke();
      component1.SetObjectPhysicsByIsGrabbed(true);
      this.isGrabbing = true;
      if ((bool) (UnityEngine.Object) this.DrawOutlineMat)
        this.DrawOutlineMat.color = !component1.grabValues.canSpin ? (!component1.grabValues.canFollow ? this.cannotDoAnythingColor : this.canFollowColor) : this.canSpinColor;
      this.outlinerCamera.LerpOutlineDist();
      if (component1.OnGrabbed != null)
        component1.OnGrabbed.Invoke();
      if (component1.OnGrabbedLocal != null)
        component1.OnGrabbedLocal.Invoke();
      if (this.OnGrabbed != null)
        this.OnGrabbed.Invoke();
      this.OnGrabbedParam?.Invoke(component1);
      if ((UnityEngine.Object) this._ChallengeMode != (UnityEngine.Object) null && this._ChallengeMode.ChallengeModeEnabled)
        ++this._ChallengeMode._Grabs;
      if ((UnityEngine.Object) this._MiniChallengeMode != (UnityEngine.Object) null && this._MiniChallengeMode.MiniChallengeModeEnabled)
        this._MiniChallengeMode.AddToGrabs();
      DreamManagerProxy component4 = GameManager.GM.GetComponent<DreamManagerProxy>();
      if (!((UnityEngine.Object) component4 != (UnityEngine.Object) null) || !component4.IsInDream())
        return;
      component4.AddToChallengeModeGrabs();
    }
  }

  public void CheckIfGrabbingThenDoDropDownObject()
  {
    if (!this.isGrabbing)
      return;
    this.DoDropDownObject();
  }

  private void DoDropDownObject(bool objectWasStolen = false)
  {
    this.justDroppedThisFrame = true;
    Portal crossedPortal;
    float reductionRatio;
    float distance = this.getResizeDistance(this.grabbedObject, out crossedPortal, out reductionRatio);
    if ((double) distance == 3.40282346638529E+38)
    {
      distance = this._maxGrabDistance;
      this.isObjectInSky = true;
    }
    else
      this.isObjectInSky = false;
    if ((double) distance == 3.40282346638529E+38 || this.isRejectProject)
    {
      if (!(bool) (UnityEngine.Object) this.soundEffectScript)
        return;
      this.soundEffectScript.play_denied_sound();
    }
    else
    {
      Vector3 position = this.grabbedObject.transform.position;
      this._EnsureObjectDetached();
      this.UpdateObjectTransformAndPropertyByDistance(this.grabbedObject, distance, crossedPortal, reductionRatio);
      this.EnlargenIfTooSmall();
      this.ReturnObjectToWorld(objectWasStolen);
      if (this.grabbedObject.GetComponent<DropTriggerScript>().grabValues.canFollow)
        this.setFollowVelocity(position);
      double num = (double) Vector3.Distance(this.transform.position, this.grabbedObject.transform.position);
      if (!(bool) (UnityEngine.Object) this.soundEffectScript)
        return;
      this.soundEffectScript.play_pop_sound_put(this.grabbedObject.GetComponent<DropTriggerScript>().SizeEstimate());
    }
  }

  public void CallReturnObjectToWorld() => this.ReturnObjectToWorld(false);

  private int GetPhotonViewID() => GameManager.GM.player.GetComponent<PhotonView>().ViewID;

  private void ReturnObjectToWorld(bool objectWasStolen)
  {
    this.grabbedObject.layer = MoSTLayer.CanGrab;
    DropTriggerScript component1 = this.grabbedObject.GetComponent<DropTriggerScript>();
    if (component1.grabValues.isGrabOnce)
    {
      this.grabbedObject.layer = MoSTLayer.Default;
      component1.GrayOut();
    }
    if (component1.grabValues.canReturn)
      component1.toReturn = true;
    component1.returnChildrenColliderLayers();
    component1.SetObjectPhysicsByIsGrabbed(false);
    if (this.isObjectInSky)
    {
      component1.SetIsKinematic(true);
    }
    else
    {
      if (component1.AllowRandomDropTorque)
      {
        Rigidbody component2 = this.grabbedObject.GetComponent<Rigidbody>();
        if ((bool) (UnityEngine.Object) component2)
        {
          Vector3 vector3 = this.LimitRandomTorqueToCameraPlane ? this.transform.forward : UnityEngine.Random.onUnitSphere;
          if (UnityEngine.Random.Range(0, 2) == 0)
            vector3 = -vector3;
          component2.AddTorque(vector3 * UnityEngine.Random.Range(this.RandomTorqueOnDrop.x, this.RandomTorqueOnDrop.y), ForceMode.VelocityChange);
        }
      }
      if ((bool) (UnityEngine.Object) component1.RandomEjection)
      {
        Rigidbody component2 = this.grabbedObject.GetComponent<Rigidbody>();
        if ((bool) (UnityEngine.Object) component2)
        {
          Vector3 axis = Quaternion.AngleAxis(UnityEngine.Random.Range(0.0f, 360f), component1.RandomEjection.forward) * component1.RandomEjection.right;
          Vector3 vector3 = Quaternion.AngleAxis(UnityEngine.Random.Range(0.0f, component1.RandomEjectionAngle), axis) * component1.RandomEjection.forward;
          float num = UnityEngine.Random.Range(0.0f, component1.RandomEjectionAcceleration);
          component2.AddForce(vector3.normalized * num, ForceMode.VelocityChange);
        }
      }
    }
    this.isGrabbing = false;
    this._MaybeSnap(this.grabbedObject, false);
    this._InvokeOnDroppedEvents(component1);
  }

  private void _InvokeOnDroppedEvents(DropTriggerScript dts)
  {
    dts.OnDropped?.Invoke();
    this.OnDropped?.Invoke();
    this.OnDroppedParam?.Invoke(dts);
    dts.OnDroppedLocal?.Invoke();
  }

  public static bool _CastRayOrSphereForObject(
    Ray ray,
    float sphereRadius,
    out RaycastHit hitInfo,
    int layerMask,
    out GameObject hitObject,
    out GameObject grabObject,
    out bool wasSingleRay)
  {
    hitObject = (GameObject) null;
    grabObject = (GameObject) null;
    wasSingleRay = true;
    bool flag = false;
    if (Physics.Raycast(ray, out hitInfo, float.PositiveInfinity, layerMask))
    {
      flag = true;
      grabObject = ResizeScript.getNearestCanGrabAncestor(hitInfo.collider.gameObject);
      if ((bool) (UnityEngine.Object) grabObject)
      {
        hitObject = hitInfo.collider.gameObject;
        flag = false;
      }
    }
    if (flag)
    {
      int num = Physics.SphereCastNonAlloc(ray, sphereRadius, ResizeScript.hitWorker, hitInfo.distance + 0.1f, layerMask);
      for (int index = 0; index < num; ++index)
      {
        GameObject nearestCanGrabAncestor = ResizeScript.getNearestCanGrabAncestor(ResizeScript.hitWorker[index].collider.gameObject);
        if ((bool) (UnityEngine.Object) nearestCanGrabAncestor)
        {
          Vector3 vector3 = ResizeScript.hitWorker[index].point - ray.origin;
          RaycastHit hitInfo1;
          if (!Physics.Raycast(new Ray(ray.origin, vector3.normalized), out hitInfo1, vector3.magnitude, layerMask) || (UnityEngine.Object) hitInfo1.collider.gameObject == (UnityEngine.Object) ResizeScript.hitWorker[index].collider.gameObject)
          {
            hitObject = ResizeScript.hitWorker[index].collider.gameObject;
            grabObject = nearestCanGrabAncestor;
            wasSingleRay = false;
            break;
          }
        }
      }
      if (!(bool) (UnityEngine.Object) hitObject)
        hitObject = hitInfo.collider.gameObject;
    }
    return (UnityEngine.Object) hitObject != (UnityEngine.Object) null;
  }

  private static bool _CastSphereForObject(
    Ray ray,
    float sphereRadius,
    float distanceToCast,
    int layerMask,
    out GameObject hitObject,
    out GameObject grabObject)
  {
    hitObject = (GameObject) null;
    grabObject = (GameObject) null;
    int num = Physics.SphereCastNonAlloc(ray, sphereRadius, ResizeScript.hitWorker, distanceToCast, layerMask);
    GameObject gameObject = (GameObject) null;
    float maxValue = float.MaxValue;
    for (int index = 0; index < num; ++index)
    {
      if ((bool) (UnityEngine.Object) ResizeScript.getNearestCanGrabAncestor(ResizeScript.hitWorker[index].collider.gameObject))
      {
        Vector3 vector3 = ResizeScript.hitWorker[index].point - ray.origin;
        RaycastHit hitInfo;
        if (!Physics.Raycast(new Ray(ray.origin, vector3.normalized), out hitInfo, vector3.magnitude, layerMask) || (UnityEngine.Object) hitInfo.collider.gameObject == (UnityEngine.Object) ResizeScript.hitWorker[index].collider.gameObject)
        {
          if ((double) vector3.magnitude < (double) maxValue)
          {
            gameObject = ResizeScript.hitWorker[index].collider.gameObject;
            float magnitude = vector3.magnitude;
            break;
          }
          break;
        }
      }
    }
    hitObject = gameObject;
    return (UnityEngine.Object) hitObject != (UnityEngine.Object) null;
  }

  private GameObject getFirstGrabbableObject(
    out Portal crossedPortal,
    out bool supressDeniedSound)
  {
    supressDeniedSound = false;
    crossedPortal = (Portal) null;
    float sphereRadius = !ReInput.isReady || ReInput.controllers.GetLastActiveController().type != ControllerType.Joystick ? this.CastRadius : this.CastRadiusForController;
    RaycastHit hitInfo;
    GameObject hitObject1;
    GameObject grabObject1;
    bool wasSingleRay;
    if (ResizeScript._CastRayOrSphereForObject(new Ray(this.transform.position, this.transform.forward), sphereRadius, out hitInfo, this._layerMaskIgnorePlayer, out hitObject1, out grabObject1, out wasSingleRay))
    {
      Portal hitPortal = this._MaybeGetHitPortal(ref hitInfo);
      GameObject hitObject2;
      GameObject grabObject2;
      if ((bool) (UnityEngine.Object) hitPortal & wasSingleRay && ResizeScript._CastRayOrSphereForObject(PortalHelper.TransformRay(hitPortal, new Ray(hitInfo.point, this.transform.forward)), sphereRadius, out hitInfo, -5, out hitObject2, out grabObject2, out wasSingleRay))
      {
        hitObject1 = hitObject2;
        if ((bool) (UnityEngine.Object) grabObject2 && !hitPortal.transform.IsChildOf(grabObject2.transform) && !hitPortal.Destination.transform.IsChildOf(grabObject2.transform))
        {
          grabObject1 = grabObject2;
          crossedPortal = hitPortal;
        }
      }
    }
    if ((bool) (UnityEngine.Object) grabObject1)
    {
      MultiplayerPlayer component = grabObject1.GetComponent<MultiplayerPlayer>();
      if ((bool) (UnityEngine.Object) component && !component.CanClonePlayer_AndMaybeDestroy())
      {
        grabObject1 = (GameObject) null;
        hitObject1 = (GameObject) null;
        crossedPortal = (Portal) null;
      }
    }
    MOSTTriggerBase mostTriggerBase = (MOSTTriggerBase) null;
    if ((bool) (UnityEngine.Object) hitObject1)
    {
      MOSTTriggerOnClick component = hitObject1.GetComponent<MOSTTriggerOnClick>();
      mostTriggerBase = (MOSTTriggerBase) component;
      if (!(bool) (UnityEngine.Object) mostTriggerBase)
        mostTriggerBase = (MOSTTriggerBase) hitObject1.GetComponentInParent<MOSTTriggerOnClickChildren>();
      if ((bool) (UnityEngine.Object) component && component.DenyGrabInParent)
        grabObject1 = (GameObject) null;
    }
    supressDeniedSound = (bool) (UnityEngine.Object) mostTriggerBase && (!mostTriggerBase.hasTriggered || mostTriggerBase.repeatableTrigger);
    if ((bool) (UnityEngine.Object) grabObject1 && this.DenyGrab != null && this.DenyGrab(grabObject1))
      grabObject1 = (GameObject) null;
    return grabObject1;
  }

  public static GameObject getNearestCanGrabAncestor(GameObject obj)
  {
    if (obj.layer == MoSTLayer.CanGrab)
      return obj;
    if ((UnityEngine.Object) obj.transform.parent == (UnityEngine.Object) null)
      return (GameObject) null;
    if (obj.layer == MoSTLayer.CannotGrab)
      return (GameObject) null;
    return obj.CompareTag(ResizeScript.ChildThatIgnoresGrabTag) ? (GameObject) null : ResizeScript.getNearestCanGrabAncestor(obj.transform.parent.gameObject);
  }

  private float _EstimateObjectSize(GameObject obj)
  {
    Vector3 size = this._EstimateObjectBounds(obj).size;
    return Mathf.Max(size.x, Mathf.Max(size.y, size.z));
  }

  private Bounds _EstimateObjectBounds(GameObject obj)
  {
    Transform transform = obj.transform;
    Bounds bounds = new Bounds(transform.position, Vector3.zero);
    Collider component = obj.GetComponent<Collider>();
    if ((bool) (UnityEngine.Object) component)
      bounds.Encapsulate(component.bounds);
    int childCount = transform.childCount;
    for (int index = 0; index < childCount; ++index)
    {
      Transform child = transform.GetChild(index);
      if (child.gameObject.activeSelf)
        bounds.Encapsulate(this._EstimateObjectBounds(child.gameObject));
    }
    return bounds;
  }

  private float _GetSmallObjectThreshold(GameObject obj)
  {
    float overlapThreshold = this.SmallObjectIgnoreOverlapThreshold;
    DropTriggerScript component = obj.GetComponent<DropTriggerScript>();
    if ((bool) (UnityEngine.Object) component && (double) component.CustomSmallObjectIgnoreOverlapThreshold != 0.0)
      overlapThreshold = component.CustomSmallObjectIgnoreOverlapThreshold;
    return overlapThreshold;
  }

  private float _EnsureObjectDoesntColliderWithPlayerByTestingOverlap(
    GameObject obj,
    float resizeDistance)
  {
    if ((double) resizeDistance == double.PositiveInfinity || (double) resizeDistance == 3.40282346638529E+38)
      return 1f;
    int num1 = 0;
    CharacterController component = GameManager.GM.player.GetComponent<CharacterController>();
    Vector3 center = component.center;
    Vector3 position1 = component.center - Vector3.up * (component.height * 0.5f - component.radius);
    Vector3 position2 = component.center + Vector3.up * (component.height * 0.5f - component.radius);
    float radius = component.radius * component.transform.localScale.x;
    Vector3 point0 = component.transform.TransformPoint(position1);
    Vector3 point1 = component.transform.TransformPoint(position2);
    float num2 = 1f;
    float b1 = 0.0f;
    float b2 = 1f;
    this.UpdateObjectTransformAndPropertyByDistance(obj, resizeDistance, (Portal) null, num2);
    float num3 = 0.0f;
    float smallObjectThreshold = this._GetSmallObjectThreshold(obj);
    if ((double) smallObjectThreshold > 0.0)
    {
      float num4 = this._EstimateObjectSize(obj);
      if ((double) num4 < (double) smallObjectThreshold)
        return 1f;
      num3 = smallObjectThreshold / num4;
    }
    for (; num1 < 10; ++num1)
    {
      int num4 = Physics.OverlapCapsuleNonAlloc(point0, point1, radius, ResizeScript.lotsOfColliders, this._layerMaskGrabbed);
      if (num4 != 0 || num1 != 0)
      {
        if (num4 > 0)
        {
          b2 = num2;
          num2 = Mathf.Lerp(num2, b1, 0.5f);
        }
        else
        {
          b1 = num2;
          num2 = Mathf.Lerp(num2, b2, 0.5f);
        }
        this.UpdateObjectTransformAndPropertyByDistance(obj, resizeDistance, (Portal) null, num2);
      }
      else
        break;
    }
    if ((double) num2 < (double) num3)
      num2 = num3;
    return num2;
  }

  private float _EnsureObjectDoesntColliderWithPlayer(
    GameObject obj,
    List<Vector3> objVertices,
    float resizeDistance,
    float furtherestDistance)
  {
    if ((double) resizeDistance == double.PositiveInfinity)
      return 1f;
    Vector3 directionToObject = this._GetDirectionToObject();
    float num = resizeDistance / this._GetMinGrabDistance();
    Matrix4x4 matrix4x4 = Matrix4x4.TRS(this.transform.position + directionToObject * resizeDistance, this._GetCurrentObjectRotationWorldSpace(), this.scaleAtMinDistance * num);
    for (int index = 0; index < objVertices.Count; ++index)
      objVertices[index] = matrix4x4.MultiplyPoint(objVertices[index]);
    Vector3 origin = this.transform.position + directionToObject * resizeDistance;
    float a = 1f;
    foreach (Vector3 objVertex in objVertices)
    {
      Vector3 direction = objVertex - origin;
      float magnitude = direction.magnitude;
      RaycastHit hitInfo;
      if (Physics.Raycast(origin, direction, out hitInfo, magnitude, this._layerMaskOnlyPlayer))
        a = Mathf.Min(a, hitInfo.distance / magnitude);
    }
    return a;
  }

  private void _PopulateRaysScreenspace(
    Camera theCamera,
    List<Vector3> objWorldSpacePoints,
    bool parallel)
  {
    Vector3 pos1 = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
    Vector3 pos2 = new Vector3(float.MinValue, float.MinValue, float.MinValue);
    foreach (Vector3 objWorldSpacePoint in objWorldSpacePoints)
    {
      Vector3 screenPoint = theCamera.WorldToScreenPoint(objWorldSpacePoint);
      if ((double) screenPoint.x < (double) pos1.x)
        pos1.x = screenPoint.x;
      if ((double) screenPoint.y < (double) pos1.y)
        pos1.y = screenPoint.y;
      if ((double) screenPoint.x > (double) pos2.x)
        pos2.x = screenPoint.x;
      if ((double) screenPoint.y > (double) pos2.y)
        pos2.y = screenPoint.y;
    }
    Ray ray1 = theCamera.ScreenPointToRay(pos1);
    Ray ray2 = theCamera.ScreenPointToRay(pos2);
    UnityEngine.Debug.DrawRay(ray1.origin, ray1.direction, Color.red);
    UnityEngine.Debug.DrawRay(ray2.origin, ray2.direction, Color.red);
    int num1 = (int) (((double) pos2.x - (double) pos1.x) / 20.0);
    int num2 = (int) (((double) pos2.y - (double) pos1.y) / 20.0);
    int num3 = Mathf.Clamp(num1, 20, 40);
    int num4 = Mathf.Clamp(num2, 20, 40);
    float num5 = (pos2.x - pos1.x) / (float) num3;
    float num6 = (pos2.y - pos1.y) / (float) num4;
    for (int index1 = 0; index1 < num4; ++index1)
    {
      float y = pos1.y + (float) index1 * num6;
      for (int index2 = 0; index2 < num3; ++index2)
      {
        Vector3 pos3 = new Vector3(pos1.x + (float) index2 * num5, y, 0.0f);
        Ray ray3 = theCamera.ScreenPointToRay(pos3);
        if (parallel)
          this.rayDirectionsWorkerPrelim.Add(ray3.direction);
        else
          this.rayListWorker.Add(ray3);
      }
    }
  }

  private void _PopulateRaysSpherical(
    Camera theCamera,
    List<Vector3> objWorldSpacePoints,
    Vector3 cameraToObjectDirection,
    bool parallel)
  {
    Vector3 position = this.transform.position;
    Vector3 right = this.transform.right;
    Vector3 up = this.transform.up;
    float a1 = float.MaxValue;
    float a2 = float.MaxValue;
    float num1 = float.MinValue;
    float num2 = float.MinValue;
    Vector3 from1 = Vector3.ProjectOnPlane(cameraToObjectDirection, right);
    Vector3 from2 = Vector3.ProjectOnPlane(cameraToObjectDirection, up);
    foreach (Vector3 objWorldSpacePoint in objWorldSpacePoints)
    {
      float b1 = Vector3.SignedAngle(from1, Vector3.ProjectOnPlane(objWorldSpacePoint - position, right), right);
      a2 = Mathf.Min(a2, b1);
      num2 = Mathf.Max(num2, b1);
      float b2 = Vector3.SignedAngle(from2, Vector3.ProjectOnPlane(objWorldSpacePoint - position, up), up);
      a1 = Mathf.Min(a1, b2);
      num1 = Mathf.Max(num1, b2);
    }
    float num3 = 0.5f;
    int min = Mathf.CeilToInt(20f);
    int max = Mathf.CeilToInt(40f);
    float num4 = num1 - a1;
    int num5 = Mathf.Clamp(Mathf.CeilToInt(num4 * num3), min, max);
    double num6 = (double) num2 - (double) a2;
    int num7 = Mathf.Clamp(Mathf.CeilToInt((float) (num6 * 0.5)), min, max);
    double num8 = (double) num4 / (double) num5;
    double num9 = num6 / (double) num7;
    for (int index1 = 0; index1 <= num7; ++index1)
    {
      Vector3 vector3 = Quaternion.AngleAxis(Mathf.Lerp(a2, num2, (float) index1 / (float) num7), right) * cameraToObjectDirection;
      for (int index2 = 0; index2 <= num5; ++index2)
      {
        Vector3 direction = Quaternion.AngleAxis(Mathf.Lerp(a1, num1, (float) index2 / (float) num5), up) * vector3;
        if (parallel)
          this.rayDirectionsWorkerPrelim.Add(direction);
        else
          this.rayListWorker.Add(new Ray(position, direction));
      }
    }
  }

  private void _PopulateRaysSphericalOLD(
    Camera theCamera,
    List<Vector3> objWorldSpacePoints,
    Vector3 cameraToObjectDirection,
    bool parallel)
  {
    Vector3 position = this.transform.position;
    Vector3 right = this.transform.right;
    Vector3 up = this.transform.up;
    float a1 = float.MaxValue;
    float a2 = float.MaxValue;
    float num1 = float.MinValue;
    float num2 = float.MinValue;
    foreach (Vector3 objWorldSpacePoint in objWorldSpacePoints)
    {
      float b1 = Vector3.SignedAngle(cameraToObjectDirection, objWorldSpacePoint - position, right);
      a2 = Mathf.Min(a2, b1);
      num2 = Mathf.Max(num2, b1);
      float b2 = Vector3.SignedAngle(cameraToObjectDirection, objWorldSpacePoint - position, up);
      a1 = Mathf.Min(a1, b2);
      num1 = Mathf.Max(num1, b2);
    }
    float num3 = 0.5f * this.TestingRayReduction;
    int min = Mathf.CeilToInt(20f * this.TestingRayReduction);
    int max = Mathf.CeilToInt(40f * this.TestingRayReduction);
    float num4 = num1 - a1;
    int num5 = Mathf.Clamp(Mathf.CeilToInt(num4 * num3), min, max);
    double num6 = (double) num2 - (double) a2;
    int num7 = Mathf.Clamp(Mathf.CeilToInt((float) (num6 * 0.5)), min, max);
    double num8 = (double) num4 / (double) num5;
    double num9 = num6 / (double) num7;
    for (int index1 = 0; index1 <= num7; ++index1)
    {
      Vector3 vector3 = Quaternion.AngleAxis(Mathf.Lerp(a2, num2, (float) index1 / (float) num7), right) * cameraToObjectDirection;
      for (int index2 = 0; index2 <= num5; ++index2)
      {
        Vector3 direction = Quaternion.AngleAxis(Mathf.Lerp(a1, num1, (float) index2 / (float) num5), up) * vector3;
        if (parallel)
          this.rayDirectionsWorkerPrelim.Add(direction);
        else
          this.rayListWorker.Add(new Ray(position, direction));
      }
    }
  }

  private float getResizeDistance(
    GameObject obj,
    out Portal crossedPortal,
    out float reductionRatio)
  {
    float num = 0.0f;
    crossedPortal = (Portal) null;
    reductionRatio = 1f;
    switch (this.RayCastType)
    {
      case GrabObjectRayCastType.SingleThread:
        num = this.getResizeDistanceWorker(obj, out crossedPortal, out reductionRatio, 1f);
        break;
      case GrabObjectRayCastType.MultiThreadImmediate:
        num = this.getResizeDistanceWorker_Parallel(obj, out crossedPortal, out reductionRatio, 1f);
        break;
      case GrabObjectRayCastType.MultiThreadDeferred:
        num = this.FinishOffTheThing(obj, out crossedPortal, out reductionRatio);
        break;
    }
    if ((double) num == double.PositiveInfinity || (double) num == 3.40282346638529E+38)
    {
      num = this.getResizeDistanceWorker(obj, out crossedPortal, out reductionRatio, 2f);
      if (((double) num == double.PositiveInfinity || (double) num == 3.40282346638529E+38) && obj.GetComponent<DropTriggerScript>().grabValues.isCloneable)
        num = this._GetMinGrabDistance();
    }
    return num;
  }

  private Mesh GetMesh(GameObject go)
  {
    Mesh mesh = (Mesh) null;
    MeshFilter component = go.GetComponent<MeshFilter>();
    if ((bool) (UnityEngine.Object) component)
      mesh = component.sharedMesh;
    return mesh;
  }

  private float getResizeDistanceWorker_Parallel(
    GameObject obj,
    out Portal crossedPortal,
    out float reductionRatio,
    float minDistanceScale)
  {
    if (!this.rayCastResults.IsCreated)
    {
      int num = 1881;
      this.rayCastResults = new NativeArray<RaycastHit>(num, Allocator.Persistent);
      this.rayCastCommands = new NativeList<RaycastCommand>(num, Allocator.Persistent);
      this.rayCastResultsPortal = new NativeArray<RaycastHit>(num, Allocator.Persistent);
      this.rayCastCommandsPortal = new NativeList<RaycastCommand>(num, Allocator.Persistent);
    }
    this.swHitGrab.Reset();
    this.swTotal.Reset();
    this.swTotal.Start();
    this.Info.DidntHitBack = 0;
    this.Info.DidntHitWall = 0;
    this.Info.DidntHitGrabbed = 0;
    this.Info.DidntHitGrabbedObjVert = 0;
    reductionRatio = 1f;
    Vector3 minDistance = this.ResetObjectToMinDistance(obj, minDistanceScale);
    this.rayDirectionsWorkerPrelim.Clear();
    this.rayDirectionsWorkerFinal.Clear();
    this.portalCommandToOriginalIndex.Clear();
    this.portalsWeHit.Clear();
    Mesh mesh = this.GetMesh(obj);
    this.swCalcBounds.Reset();
    this.swCalcBounds.Start();
    this.objWorldSpacePoints.Clear();
    this.objPoints.Clear();
    ReducedMeshForRayCasting component1 = obj.GetComponent<ReducedMeshForRayCasting>();
    Transform objToWorldTransform = obj.transform;
    if ((bool) (UnityEngine.Object) component1)
      component1.GetObjectSpaceVertices(this.objPoints, out objToWorldTransform);
    else
      mesh.GetVertices(this.objPoints);
    this.objWorldSpacePoints.AddRange((IEnumerable<Vector3>) this.objPoints);
    bool flag = this.objWorldSpacePoints.Count < 200;
    Camera component2 = this.GetComponent<Camera>();
    for (int index = 0; index < this.objWorldSpacePoints.Count; ++index)
    {
      this.objWorldSpacePoints[index] = objToWorldTransform.TransformPoint(this.objWorldSpacePoints[index]);
      if (flag)
        this.rayDirectionsWorkerPrelim.Add(this.objWorldSpacePoints[index] - this.transform.position);
    }
    this.Info.ObjectVertexCount = this.rayDirectionsWorkerPrelim.Count;
    if (this.UseSphericalBounds)
      this._PopulateRaysSpherical(component2, this.objWorldSpacePoints, minDistance, true);
    else
      this._PopulateRaysScreenspace(component2, this.objWorldSpacePoints, true);
    this.swCalcBounds.Stop();
    this.Info.CalcBoundsMS = (float) (this.swCalcBounds.Elapsed.TotalSeconds * 1000.0);
    this.Info.ScreenSpaceVertexCount = this.rayDirectionsWorkerPrelim.Count - this.Info.ObjectVertexCount;
    if (GameManager.GM.debugModeOn)
      GameManager.GM.MyLog("Rays shot: " + (object) this.rayDirectionsWorkerPrelim.Count);
    int num1 = 0;
    float resizeDistance = float.MaxValue;
    float num2 = float.MaxValue;
    crossedPortal = (Portal) null;
    float furtherestDistance = 0.0f;
    float minGrabDistance = this._GetMinGrabDistance();
    this.rayCastCommands.Clear();
    Vector3 position = this.transform.position;
    int count = this.rayDirectionsWorkerPrelim.Count;
    Physics.SyncTransforms();
    for (int index = 0; index < count; ++index)
      this.rayCastCommands.Add(new RaycastCommand(position, this.rayDirectionsWorkerPrelim[index], float.PositiveInfinity, this._layerMaskGrabbed));
    JobHandle jobHandle = RaycastCommand.ScheduleBatch((NativeArray<RaycastCommand>) this.rayCastCommands, this.rayCastResults, 1);
    jobHandle.Complete();
    this.rayCastCommands.Clear();
    RaycastHit rayCastResult1;
    for (int index = 0; index < count; ++index)
    {
      rayCastResult1 = this.rayCastResults[index];
      if ((UnityEngine.Object) rayCastResult1.collider != (UnityEngine.Object) null)
        this.rayCastCommands.Add(new RaycastCommand(position, this.rayDirectionsWorkerPrelim[index], float.PositiveInfinity, this._layerMaskIgnoreGrabbed));
    }
    int length1 = this.rayCastCommands.Length;
    jobHandle = RaycastCommand.ScheduleBatch((NativeArray<RaycastCommand>) this.rayCastCommands, this.rayCastResults, 1);
    jobHandle.Complete();
    this.rayCastCommands.Clear();
    this.rayCastCommandsPortal.Clear();
    this.forwardHitDistances.Clear();
    for (int index1 = 0; index1 < length1; ++index1)
    {
      RaycastHit rayCastResult2 = this.rayCastResults[index1];
      if ((UnityEngine.Object) rayCastResult2.collider != (UnityEngine.Object) null)
      {
        Portal hitPortal = this._MaybeGetHitPortal(ref rayCastResult2);
        if ((bool) (UnityEngine.Object) hitPortal)
        {
          if (!this.portalsWeHit.Contains(hitPortal))
          {
            PortalHelper.GetConversionMatrix(hitPortal, out this.portalMatrices[this.portalsWeHit.Count]);
            this.portalsWeHit.Add(hitPortal);
          }
          int index2 = this.portalsWeHit.IndexOf(hitPortal);
          Ray ray = new Ray(this.portalMatrices[index2].MultiplyPoint(rayCastResult2.point), this.portalMatrices[index2].MultiplyVector(rayCastResult2.point - position));
          ray.origin += Vector3.Normalize(ray.direction) * 0.1f;
          this.rayCastCommandsPortal.Add(new RaycastCommand(ray.origin, ray.direction, float.PositiveInfinity, this._layerMaskIgnoreGrabbed));
          this.portalCommandToOriginalIndex.Add(new ResizeScript.PortalAndIndex()
          {
            PortalIndex = index2,
            BackRayIndex = this.rayCastCommands.Length
          });
        }
        Vector3 point = rayCastResult2.point;
        Vector3 direction = this.transform.position - point;
        this.rayCastCommands.Add(new RaycastCommand(point - direction * 0.0f, direction, float.PositiveInfinity, this._layerMaskGrabbed));
        this.forwardHitDistances.Add(rayCastResult2.distance);
      }
    }
    int length2 = this.rayCastCommandsPortal.Length;
    int length3 = this.rayCastCommands.Length;
    if (length2 > 0)
    {
      JobHandle job0 = RaycastCommand.ScheduleBatch((NativeArray<RaycastCommand>) this.rayCastCommandsPortal, this.rayCastResultsPortal, 1);
      jobHandle = RaycastCommand.ScheduleBatch((NativeArray<RaycastCommand>) this.rayCastCommands, this.rayCastResults, 1);
      JobHandle job1 = jobHandle;
      JobHandle.CombineDependencies(job0, job1).Complete();
    }
    else
    {
      jobHandle = RaycastCommand.ScheduleBatch((NativeArray<RaycastCommand>) this.rayCastCommands, this.rayCastResults, 1);
      jobHandle.Complete();
    }
    int index3 = 0;
    int num3 = 0;
    for (int index1 = 0; index1 < length3; ++index1)
    {
      int index2 = -1;
      if (index3 < length2 && this.portalCommandToOriginalIndex[index3].BackRayIndex == index1)
      {
        index2 = index3;
        ++index3;
      }
      RaycastHit rayCastResult2 = this.rayCastResults[index1];
      if ((bool) (UnityEngine.Object) rayCastResult2.collider)
      {
        Portal portal = (Portal) null;
        float num4 = 0.0f;
        if (index2 != -1)
        {
          rayCastResult1 = this.rayCastResultsPortal[index2];
          if ((bool) (UnityEngine.Object) rayCastResult1.collider)
          {
            rayCastResult1 = this.rayCastResultsPortal[index2];
            num4 = (float) (0.100000001490116 + (double) rayCastResult1.distance);
            portal = this.portalsWeHit[this.portalCommandToOriginalIndex[index2].PortalIndex];
            ++num1;
          }
        }
        ++num3;
        float forwardHitDistance = this.forwardHitDistances[index1];
        float num5 = rayCastResult2.distance - 0.0f;
        float num6 = (float) ((double) minGrabDistance * ((double) forwardHitDistance + (double) num4) / ((double) forwardHitDistance - (double) num5));
        float num7 = (float) ((double) minGrabDistance * (double) forwardHitDistance / ((double) forwardHitDistance - (double) num5));
        if ((bool) (UnityEngine.Object) portal && portal.AllowObjectsOnBoundary)
          num7 = num6;
        if ((double) num6 < (double) resizeDistance && (double) num6 > 0.0)
        {
          resizeDistance = num6;
          crossedPortal = portal;
        }
        if ((double) num7 < (double) num2 && (double) num7 > 0.0)
          num2 = num7;
      }
    }
    if ((bool) (UnityEngine.Object) crossedPortal && num1 < num3 || !(bool) (UnityEngine.Object) crossedPortal)
    {
      crossedPortal = (Portal) null;
      if ((double) num2 != double.PositiveInfinity && (double) num2 < 3.40282346638529E+38)
        resizeDistance = num2;
    }
    this.swEnsureNoPlayerCollide.Reset();
    this.swEnsureNoPlayerCollide.Start();
    if (!(bool) (UnityEngine.Object) crossedPortal)
      reductionRatio = !this.UseOverlapForAvoidingPlayerCollision ? this._EnsureObjectDoesntColliderWithPlayer(obj, this.objPoints, resizeDistance, furtherestDistance) : this._EnsureObjectDoesntColliderWithPlayerByTestingOverlap(obj, resizeDistance);
    this.swEnsureNoPlayerCollide.Stop();
    this.Info.PlayerNoCollideMS = (float) (this.swEnsureNoPlayerCollide.Elapsed.TotalSeconds * 1000.0);
    this.Info.ReductionRatio = reductionRatio;
    this.swTotal.Stop();
    this.Info.TotalMS = (float) (this.swTotal.Elapsed.TotalSeconds * 1000.0);
    this.Info.TotalMSInclusive = this.Info.TotalMS;
    this.Info.HitGrabMS = (float) (this.swHitGrab.Elapsed.TotalSeconds * 1000.0);
    return resizeDistance;
  }

  private void getResizeDistanceWorker_Parallel2(GameObject obj, float minDistanceScale)
  {
    if (!this.rayCastResults.IsCreated)
    {
      this.rayCastResults = new NativeArray<RaycastHit>(1881, Allocator.Persistent);
      this.rayCastCommands = new NativeList<RaycastCommand>(1881, Allocator.Persistent);
      this.rayCastResultsPortal = new NativeArray<RaycastHit>(1881, Allocator.Persistent);
      this.rayCastCommandsPortal = new NativeList<RaycastCommand>(1881, Allocator.Persistent);
    }
    if (!this.filteredRayIndices.IsCreated)
      this.filteredRayIndices = new NativeList<int>(1881, Allocator.Persistent);
    this.swHitGrab.Reset();
    this.swTotal.Reset();
    this.swTotal.Start();
    this.swInclusive.Reset();
    this.swInclusive.Start();
    this.Info.DidntHitBack = 0;
    this.Info.DidntHitWall = 0;
    this.Info.DidntHitGrabbed = 0;
    this.Info.DidntHitGrabbedObjVert = 0;
    Vector3 minDistance = this.ResetObjectToMinDistance(obj, minDistanceScale);
    this.rayDirectionsWorkerPrelim.Clear();
    this.rayDirectionsWorkerFinal.Clear();
    this.portalCommandToOriginalIndex.Clear();
    this.portalsWeHit.Clear();
    this.filteredRayIndices.Clear();
    Mesh mesh = this.GetMesh(obj);
    this.swCalcBounds.Reset();
    this.swCalcBounds.Start();
    this.objWorldSpacePoints.Clear();
    this.objPoints.Clear();
    ReducedMeshForRayCasting component1 = obj.GetComponent<ReducedMeshForRayCasting>();
    Transform objToWorldTransform = obj.transform;
    if ((bool) (UnityEngine.Object) component1)
      component1.GetObjectSpaceVertices(this.objPoints, out objToWorldTransform);
    else
      mesh.GetVertices(this.objPoints);
    this.objWorldSpacePoints.AddRange((IEnumerable<Vector3>) this.objPoints);
    bool flag = this.objWorldSpacePoints.Count < 200;
    Camera component2 = this.GetComponent<Camera>();
    for (int index = 0; index < this.objWorldSpacePoints.Count; ++index)
    {
      this.objWorldSpacePoints[index] = objToWorldTransform.TransformPoint(this.objWorldSpacePoints[index]);
      if (flag)
        this.rayDirectionsWorkerPrelim.Add(this.objWorldSpacePoints[index] - this.transform.position);
    }
    this.Info.ObjectVertexCount = this.rayDirectionsWorkerPrelim.Count;
    if (this.UseSphericalBounds)
      this._PopulateRaysSpherical(component2, this.objWorldSpacePoints, minDistance, true);
    else
      this._PopulateRaysScreenspace(component2, this.objWorldSpacePoints, true);
    this.swCalcBounds.Stop();
    this.Info.CalcBoundsMS = (float) (this.swCalcBounds.Elapsed.TotalSeconds * 1000.0);
    this.Info.ScreenSpaceVertexCount = this.rayDirectionsWorkerPrelim.Count - this.Info.ObjectVertexCount;
    if (GameManager.GM.debugModeOn)
      GameManager.GM.MyLog("Rays shot: " + (object) this.rayDirectionsWorkerPrelim.Count);
    this.rayCastCommands.Clear();
    Vector3 position = this.transform.position;
    int count = this.rayDirectionsWorkerPrelim.Count;
    Physics.SyncTransforms();
    for (int index = 0; index < count; ++index)
      this.rayCastCommands.Add(new RaycastCommand(position, this.rayDirectionsWorkerPrelim[index], float.PositiveInfinity, this._layerMaskGrabbed));
    new ResizeScript.FilterRayHitsJob()
    {
      PrelimResults = this.rayCastResults
    }.ScheduleAppend<ResizeScript.FilterRayHitsJob>(this.filteredRayIndices, this.rayCastCommands.Length, 1, RaycastCommand.ScheduleBatch((NativeArray<RaycastCommand>) this.rayCastCommands, this.rayCastResults, 1)).Complete();
    int length = this.filteredRayIndices.Length;
    NativeArray<RaycastCommand> commands = new NativeArray<RaycastCommand>(length, Allocator.TempJob);
    JobHandle dependsOn = new ResizeScript.ConstructMainRaysJob()
    {
      LayerMask = this._layerMaskIgnoreGrabbed,
      Origin = position,
      FilteredIndices = ((NativeArray<int>) this.filteredRayIndices),
      UnfilteredResults = this.rayCastResults,
      MainRays = commands
    }.Schedule<ResizeScript.ConstructMainRaysJob>(length, 1);
    RaycastCommand.ScheduleBatch(commands, this.rayCastResults, 1, dependsOn).Complete();
    this.rayCastCommands.Clear();
    this.rayCastCommandsPortal.Clear();
    this.forwardHitDistances.Clear();
    for (int index1 = 0; index1 < length; ++index1)
    {
      RaycastHit rayCastResult = this.rayCastResults[index1];
      if ((UnityEngine.Object) rayCastResult.collider != (UnityEngine.Object) null)
      {
        Portal hitPortal = this._MaybeGetHitPortal(ref rayCastResult);
        if ((bool) (UnityEngine.Object) hitPortal)
        {
          if (!this.portalsWeHit.Contains(hitPortal))
          {
            PortalHelper.GetConversionMatrix(hitPortal, out this.portalMatrices[this.portalsWeHit.Count]);
            this.portalsWeHit.Add(hitPortal);
          }
          int index2 = this.portalsWeHit.IndexOf(hitPortal);
          Ray ray = new Ray(this.portalMatrices[index2].MultiplyPoint(rayCastResult.point), this.portalMatrices[index2].MultiplyVector(rayCastResult.point - position));
          ray.origin += Vector3.Normalize(ray.direction) * 0.1f;
          this.rayCastCommandsPortal.Add(new RaycastCommand(ray.origin, ray.direction, float.PositiveInfinity, this._layerMaskIgnoreGrabbed));
          this.portalCommandToOriginalIndex.Add(new ResizeScript.PortalAndIndex()
          {
            PortalIndex = index2,
            BackRayIndex = this.rayCastCommands.Length
          });
        }
        Vector3 point = rayCastResult.point;
        Vector3 direction = this.transform.position - point;
        this.rayCastCommands.Add(new RaycastCommand(point - direction * 0.0f, direction, float.PositiveInfinity, this._layerMaskGrabbed));
        this.forwardHitDistances.Add(rayCastResult.distance);
      }
    }
    commands.Dispose();
    this.portalRayCount = this.rayCastCommandsPortal.Length;
    this.returnRayCount = this.rayCastCommands.Length;
    this.handleToWaitFor = this.portalRayCount <= 0 ? RaycastCommand.ScheduleBatch((NativeArray<RaycastCommand>) this.rayCastCommands, this.rayCastResults, 1) : JobHandle.CombineDependencies(RaycastCommand.ScheduleBatch((NativeArray<RaycastCommand>) this.rayCastCommandsPortal, this.rayCastResultsPortal, 1), RaycastCommand.ScheduleBatch((NativeArray<RaycastCommand>) this.rayCastCommands, this.rayCastResults, 1));
    this.swInclusive.Stop();
  }

  private float FinishOffTheThing(
    GameObject obj,
    out Portal crossedPortal,
    out float reductionRatio)
  {
    this.swInclusive.Start();
    this.handleToWaitFor.Complete();
    int num1 = 0;
    float minGrabDistance = this._GetMinGrabDistance();
    float resizeDistance = float.MaxValue;
    float num2 = float.MaxValue;
    crossedPortal = (Portal) null;
    reductionRatio = 1f;
    float furtherestDistance = 0.0f;
    int index1 = 0;
    int num3 = 0;
    for (int index2 = 0; index2 < this.returnRayCount; ++index2)
    {
      int index3 = -1;
      if (index1 < this.portalRayCount && this.portalCommandToOriginalIndex[index1].BackRayIndex == index2)
      {
        index3 = index1;
        ++index1;
      }
      RaycastHit rayCastResult = this.rayCastResults[index2];
      if ((bool) (UnityEngine.Object) rayCastResult.collider)
      {
        Portal portal = (Portal) null;
        float num4 = 0.0f;
        if (index3 != -1)
        {
          RaycastHit raycastHit = this.rayCastResultsPortal[index3];
          if ((bool) (UnityEngine.Object) raycastHit.collider)
          {
            raycastHit = this.rayCastResultsPortal[index3];
            num4 = (float) (0.100000001490116 + (double) raycastHit.distance);
            portal = this.portalsWeHit[this.portalCommandToOriginalIndex[index3].PortalIndex];
            ++num1;
          }
        }
        ++num3;
        float forwardHitDistance = this.forwardHitDistances[index2];
        float num5 = rayCastResult.distance - 0.0f;
        float num6 = (float) ((double) minGrabDistance * ((double) forwardHitDistance + (double) num4) / ((double) forwardHitDistance - (double) num5));
        float num7 = (float) ((double) minGrabDistance * (double) forwardHitDistance / ((double) forwardHitDistance - (double) num5));
        if ((bool) (UnityEngine.Object) portal && portal.AllowObjectsOnBoundary)
          num7 = num6;
        if ((double) num6 < (double) resizeDistance && (double) num6 > 0.0)
        {
          resizeDistance = num6;
          crossedPortal = portal;
        }
        if ((double) num7 < (double) num2 && (double) num7 > 0.0)
          num2 = num7;
      }
    }
    if ((bool) (UnityEngine.Object) crossedPortal && num1 < num3 || !(bool) (UnityEngine.Object) crossedPortal)
    {
      crossedPortal = (Portal) null;
      if ((double) num2 != double.PositiveInfinity && (double) num2 < 3.40282346638529E+38)
        resizeDistance = num2;
    }
    this.swEnsureNoPlayerCollide.Reset();
    this.swEnsureNoPlayerCollide.Start();
    if (!(bool) (UnityEngine.Object) crossedPortal)
      reductionRatio = !this.UseOverlapForAvoidingPlayerCollision ? this._EnsureObjectDoesntColliderWithPlayer(obj, this.objPoints, resizeDistance, furtherestDistance) : this._EnsureObjectDoesntColliderWithPlayerByTestingOverlap(obj, resizeDistance);
    this.swEnsureNoPlayerCollide.Stop();
    this.Info.PlayerNoCollideMS = (float) (this.swEnsureNoPlayerCollide.Elapsed.TotalSeconds * 1000.0);
    this.Info.ReductionRatio = reductionRatio;
    this.swTotal.Stop();
    this.swInclusive.Stop();
    this.Info.TotalMS = (float) (this.swTotal.Elapsed.TotalSeconds * 1000.0);
    ref ResizeInfo local1 = ref this.Info;
    TimeSpan elapsed = this.swInclusive.Elapsed;
    double num8 = elapsed.TotalSeconds * 1000.0;
    local1.TotalMSInclusive = (float) num8;
    ref ResizeInfo local2 = ref this.Info;
    elapsed = this.swHitGrab.Elapsed;
    double num9 = elapsed.TotalSeconds * 1000.0;
    local2.HitGrabMS = (float) num9;
    return resizeDistance;
  }

  private float getResizeDistanceWorker(
    GameObject obj,
    out Portal crossedPortal,
    out float reductionRatio,
    float minDistanceScale)
  {
    this.swHitGrab.Reset();
    this.swTotal.Reset();
    this.swTotal.Start();
    this.Info.DidntHitBack = 0;
    this.Info.DidntHitWall = 0;
    this.Info.DidntHitGrabbed = 0;
    this.Info.DidntHitGrabbedObjVert = 0;
    reductionRatio = 1f;
    Vector3 minDistance = this.ResetObjectToMinDistance(obj, minDistanceScale);
    this.rayListWorker.Clear();
    Mesh mesh = this.GetMesh(obj);
    this.swCalcBounds.Reset();
    this.swCalcBounds.Start();
    this.objWorldSpacePoints.Clear();
    this.objPoints.Clear();
    ReducedMeshForRayCasting component1 = obj.GetComponent<ReducedMeshForRayCasting>();
    Transform objToWorldTransform = obj.transform;
    if ((bool) (UnityEngine.Object) component1)
      component1.GetObjectSpaceVertices(this.objPoints, out objToWorldTransform);
    else
      mesh.GetVertices(this.objPoints);
    this.objWorldSpacePoints.AddRange((IEnumerable<Vector3>) this.objPoints);
    bool flag = this.objWorldSpacePoints.Count < 200;
    Camera component2 = this.GetComponent<Camera>();
    for (int index = 0; index < this.objWorldSpacePoints.Count; ++index)
    {
      this.objWorldSpacePoints[index] = objToWorldTransform.TransformPoint(this.objWorldSpacePoints[index]);
      if (flag)
        this.rayListWorker.Add(new Ray(this.transform.position, this.objWorldSpacePoints[index] - this.transform.position));
    }
    this.Info.ObjectVertexCount = this.rayListWorker.Count;
    if (this.UseSphericalBounds)
      this._PopulateRaysSpherical(component2, this.objWorldSpacePoints, minDistance, false);
    else
      this._PopulateRaysScreenspace(component2, this.objWorldSpacePoints, false);
    this.swCalcBounds.Stop();
    this.Info.CalcBoundsMS = (float) (this.swCalcBounds.Elapsed.TotalSeconds * 1000.0);
    this.Info.ScreenSpaceVertexCount = this.rayListWorker.Count - this.Info.ObjectVertexCount;
    if (GameManager.GM.debugModeOn)
      GameManager.GM.MyLog("Rays shot: " + (object) this.rayListWorker.Count);
    int num1 = 0;
    int num2 = 0;
    float resizeDistance = float.MaxValue;
    float num3 = float.MaxValue;
    crossedPortal = (Portal) null;
    float maxCastDistance = 0.0f;
    float minGrabDistance = this._GetMinGrabDistance();
    for (int index = 0; index < this.rayListWorker.Count; ++index)
    {
      Ray forwardRay = this.rayListWorker[index];
      float distance;
      float distanceNonPortal;
      Portal crossedPortal1;
      if (this.getCurrentRayResizeDistance(minGrabDistance, forwardRay, out distance, out distanceNonPortal, out crossedPortal1, ref maxCastDistance, index < this.Info.ObjectVertexCount))
      {
        if ((bool) (UnityEngine.Object) crossedPortal1)
          ++num1;
        ++num2;
        if ((bool) (UnityEngine.Object) crossedPortal1 && crossedPortal1.AllowObjectsOnBoundary)
          distanceNonPortal = distance;
        if ((double) distance < (double) resizeDistance && (double) distance > 0.0)
        {
          resizeDistance = distance;
          crossedPortal = crossedPortal1;
        }
        if ((double) distanceNonPortal < (double) num3 && (double) distanceNonPortal > 0.0)
          num3 = distanceNonPortal;
      }
    }
    if ((bool) (UnityEngine.Object) crossedPortal && num1 < num2 || !(bool) (UnityEngine.Object) crossedPortal)
    {
      crossedPortal = (Portal) null;
      if ((double) num3 != double.PositiveInfinity && (double) num3 < 3.40282346638529E+38)
        resizeDistance = num3;
    }
    this.swEnsureNoPlayerCollide.Reset();
    this.swEnsureNoPlayerCollide.Start();
    if (!(bool) (UnityEngine.Object) crossedPortal)
      reductionRatio = !this.UseOverlapForAvoidingPlayerCollision ? this._EnsureObjectDoesntColliderWithPlayer(obj, this.objPoints, resizeDistance, maxCastDistance) : this._EnsureObjectDoesntColliderWithPlayerByTestingOverlap(obj, resizeDistance);
    this.swEnsureNoPlayerCollide.Stop();
    this.Info.PlayerNoCollideMS = (float) (this.swEnsureNoPlayerCollide.Elapsed.TotalSeconds * 1000.0);
    this.Info.ReductionRatio = reductionRatio;
    this.swTotal.Stop();
    this.Info.TotalMS = (float) (this.swTotal.Elapsed.TotalSeconds * 1000.0);
    this.Info.TotalMSInclusive = this.Info.TotalMS;
    this.Info.HitGrabMS = (float) (this.swHitGrab.Elapsed.TotalSeconds * 1000.0);
    return resizeDistance;
  }

  private Portal _MaybeGetHitPortal(ref RaycastHit hit)
  {
    Portal portal = (Portal) null;
    if (hit.collider.gameObject.layer == MoSTLayer.PortalHitTest)
    {
      PortalHitTestLink component = hit.collider.GetComponent<PortalHitTestLink>();
      if ((bool) (UnityEngine.Object) component && (bool) (UnityEngine.Object) component.Portal && component.Portal.CanProjectThroughMe)
        portal = component.Portal;
    }
    return portal;
  }

  private bool getCurrentRayResizeDistance(
    float minGrabDistance,
    Ray forwardRay,
    out float distance,
    out float distanceNonPortal,
    out Portal crossedPortal,
    ref float maxCastDistance,
    bool isObjVert)
  {
    this.swHitGrab.Start();
    if (Physics.Raycast(this.transform.position, forwardRay.direction, float.PositiveInfinity, this._layerMaskGrabbed))
    {
      this.swHitGrab.Stop();
      RaycastHit hitInfo1;
      if (Physics.Raycast(this.transform.position, forwardRay.direction, out hitInfo1, float.PositiveInfinity, this._layerMaskIgnoreGrabbed))
      {
        maxCastDistance = Mathf.Max(hitInfo1.distance, maxCastDistance);
        if (hitInfo1.collider.CompareTag(ResizeScript.StopProjectionTag))
          this.isRejectProject = true;
        if (this.isEnableDebug)
          UnityEngine.Debug.DrawLine(this.transform.position, hitInfo1.point, Color.blue);
        Vector3 point = hitInfo1.point;
        Vector3 direction = this.transform.position - point;
        float num1 = 0.0f;
        Portal hitPortal = this._MaybeGetHitPortal(ref hitInfo1);
        crossedPortal = (Portal) null;
        if ((bool) (UnityEngine.Object) hitPortal)
        {
          Ray ray = PortalHelper.TransformRay(hitPortal, new Ray(hitInfo1.point, forwardRay.direction));
          ray.origin += Vector3.Normalize(ray.direction) * 0.1f;
          RaycastHit hitInfo2;
          if (Physics.Raycast(ray.origin, ray.direction, out hitInfo2, float.PositiveInfinity, this._layerMaskIgnoreGrabbed))
          {
            crossedPortal = hitPortal;
            num1 = 0.1f + hitInfo2.distance;
          }
          else
          {
            distance = float.PositiveInfinity;
            distanceNonPortal = float.PositiveInfinity;
            return false;
          }
        }
        RaycastHit hitInfo3;
        if (Physics.Raycast(point - direction * 0.0f, direction, out hitInfo3, float.PositiveInfinity, this._layerMaskGrabbed))
        {
          float num2 = hitInfo3.distance - 0.0f;
          distance = (float) ((double) minGrabDistance * ((double) hitInfo1.distance + (double) num1) / ((double) hitInfo1.distance - (double) num2));
          distanceNonPortal = (float) ((double) minGrabDistance * (double) hitInfo1.distance / ((double) hitInfo1.distance - (double) num2));
          return true;
        }
        ++this.Info.DidntHitBack;
        distance = float.PositiveInfinity;
        distanceNonPortal = float.PositiveInfinity;
        return false;
      }
      ++this.Info.DidntHitWall;
      distance = float.PositiveInfinity;
      distanceNonPortal = float.PositiveInfinity;
      crossedPortal = (Portal) null;
      return false;
    }
    this.swHitGrab.Stop();
    ++this.Info.DidntHitGrabbed;
    if (isObjVert)
      ++this.Info.DidntHitGrabbedObjVert;
    distance = -1f;
    distanceNonPortal = float.PositiveInfinity;
    crossedPortal = (Portal) null;
    return false;
  }

  private void setFollowVelocity(Vector3 grabbed_Pos)
  {
    Vector3 vector3 = this.transform.parent.GetComponent<CharacterMotor>().GetVelocity();
    vector3 = vector3.normalized;
    Vector3 vector = (this.grabbedObject.transform.position - this.prevPosition) * 65f;
    float maxLength = 20f;
    Rigidbody component = this.grabbedObject.GetComponent<Rigidbody>();
    if (!(bool) (UnityEngine.Object) component)
      return;
    component.velocity = Vector3.ClampMagnitude(vector, maxLength);
  }

  public void ScaleObject(float scaleFactor) => this.scaleAtMinDistance *= scaleFactor;

  private void SetScaleAtMinDistance(GameObject obj, float initialRatio, Portal crossedPortal)
  {
    float num = 1f;
    if ((bool) (UnityEngine.Object) crossedPortal)
      num = 1f / PortalHelper.CalculateFromToPortalScale(crossedPortal);
    this.scaleAtMinDistance = obj.transform.localScale * initialRatio * num;
    Rigidbody component1 = this.grabbedObject.GetComponent<Rigidbody>();
    this.massAtMinDistance = !(bool) (UnityEngine.Object) component1 ? 0.0f : Mathf.Pow(initialRatio, 3f) * component1.mass;
    this.grabbedMinGrabDistance = this._GetMinGrabDistance();
    DropTriggerScript component2 = obj.GetComponent<DropTriggerScript>();
    if ((double) component2.maximumAllowedMass <= 0.0)
      return;
    this.massAtMinDistance = Mathf.Pow(initialRatio, 3f) * component2.hiddenMassIgnoringMaximum;
  }

  private float _GetLerpProgress()
  {
    float num = (float) (1.0 - (double) this.curLerpingTime / 0.800000011920929);
    return (float) (1.0 - (double) num * (double) num);
  }

  private Vector3 _GetDirectionToObject()
  {
    Vector3 b = this.transform.TransformVector(Vector3.Normalize(this.positionInCameraSpaceOriginalFinal));
    return this.isLerpingToPosition ? Vector3.Slerp(this.transform.TransformVector(Vector3.Normalize(this.positionInCameraSpaceOriginal)), b, this._GetLerpProgress()).normalized : b.normalized;
  }

  private Vector3 ResetObjectToMinDistance(GameObject obj, float minDistanceScale)
  {
    Vector3 directionToObject = this._GetDirectionToObject();
    obj.transform.rotation = this._GetCurrentObjectRotationWorldSpace();
    obj.transform.position = this.transform.position + directionToObject * this._GetMinGrabDistance() * minDistanceScale;
    obj.transform.localScale = this.scaleAtMinDistance;
    obj.GetComponent<DropTriggerScript>().UpdateMassBasedOnScale();
    return directionToObject;
  }

  private void UpdateObjectTransformAndPropertyByDistance(
    GameObject obj,
    float distance,
    Portal crossedPortal,
    float reductionRatio)
  {
    DropTriggerScript component1 = obj.GetComponent<DropTriggerScript>();
    distance *= 0.99f * component1.grabValues.DistanceScaleModifier;
    Vector3 directionToObject = this._GetDirectionToObject();
    if ((bool) (UnityEngine.Object) crossedPortal)
    {
      float num1 = distance;
      Vector3 position = this.transform.position;
      Vector3 direction1 = directionToObject;
      Quaternion rotationWorldSpace = this._GetCurrentObjectRotationWorldSpace();
      if (this.isEnableDebug)
        UnityEngine.Debug.DrawRay(position, direction1 * 3f, Color.magenta);
      Ray ray1 = new Ray(position, direction1);
      float enter;
      if (!crossedPortal.GetPortalPlane().Raycast(ray1, out enter))
        enter = num1;
      if (this.isEnableDebug)
        UnityEngine.Debug.DrawRay(position, ray1.direction * enter, Color.green);
      Vector3 origin1 = ray1.origin + ray1.direction * enter;
      double num2 = 0.0 + (double) enter * (double) PortalHelper.CalculateFromToPortalScale(crossedPortal);
      float num3 = num1 - enter;
      Ray ray2 = PortalHelper.TransformRay(crossedPortal, new Ray(origin1, direction1));
      Vector3 origin2 = ray2.origin;
      Vector3 direction2 = ray2.direction;
      Quaternion quaternion = PortalHelper.TransformRotation(crossedPortal, rotationWorldSpace);
      if (this.isEnableDebug)
        UnityEngine.Debug.DrawRay(origin2, num3 * direction2, Color.green);
      double num4 = (double) num3;
      float num5 = (float) (num2 + num4) / this._GetMinGrabDistance();
      obj.transform.rotation = quaternion;
      obj.transform.position = origin2 + num3 * direction2;
      obj.transform.localScale = this.scaleAtMinDistance * num5;
    }
    else
    {
      float num = distance / this._GetMinGrabDistance();
      obj.transform.rotation = this._GetCurrentObjectRotationWorldSpace();
      obj.transform.position = this.transform.position + distance * directionToObject;
      obj.transform.localScale = this.scaleAtMinDistance * num * reductionRatio;
    }
    component1.UpdateMassBasedOnScale();
    Rigidbody component2 = obj.GetComponent<Rigidbody>();
    if (!(bool) (UnityEngine.Object) component2)
      return;
    component2.position = obj.transform.position;
  }

  public float getGrabDistance() => this._GetMinGrabDistance();

  private void _UpdateGrabSizeStuffWhenGrabbing()
  {
    if ((double) this.grabbedMinGrabDistance == (double) this._GetMinGrabDistance())
      return;
    float num = this._GetMinGrabDistance() / this.grabbedMinGrabDistance;
    this.grabbedMinGrabDistance = this._GetMinGrabDistance();
    this.scaleAtMinDistance *= num;
    this.massAtMinDistance *= num;
  }

  public void setGrabDistance(float f)
  {
  }

  public void TurnPlayerGrabOffNextFrame() => this.notAllowedToGrab = true;

  public void TurnOffGrabDeniedSoundNextFrame() => this.turnOffGrabDeniedSoundNextFrame = true;

  public void ToggleImmediateDropAndNoLerp()
  {
    this.dontLerpObjectsToCenter = !this.dontLerpObjectsToCenter;
    this.immediatelyDropObjects = !this.immediatelyDropObjects;
  }

  public void StartHoldRotateTimer() => this.holdRotateTutorialTimer = 3f;

  public bool GetGrabbedObject_ButtonPromptBool() => !((UnityEngine.Object) this.grabbedObject == (UnityEngine.Object) null) && this.grabbedObject.GetComponent<DropTriggerScript>().showsButtonPromptForConsoles;

  public bool JustDroppedThisFrame() => this.justDroppedThisFrame;

  private bool ShouldUseVerticalHandCursor(GameObject obj)
  {
    Vector3 possibleAxis0;
    Vector3 possibleAxis1;
    Plane facingPlaneOut;
    this.GetPossibleAxes(obj, out possibleAxis0, out possibleAxis1, out facingPlaneOut);
    Vector3 finalAxis = this.GetFinalAxis(facingPlaneOut, obj, possibleAxis0, possibleAxis1);
    float num = Mathf.Abs(Vector3.Dot(finalAxis, this.transform.right));
    return (double) Mathf.Abs(Vector3.Dot(finalAxis, this.transform.up)) < (double) num;
  }

  private void GetPossibleAxes(
    GameObject grabbedObjectIn,
    out Vector3 possibleAxis0,
    out Vector3 possibleAxis1,
    out Plane facingPlaneOut)
  {
    float num1 = Mathf.Abs(Vector3.Dot(this.transform.forward, grabbedObjectIn.transform.right));
    float num2 = Mathf.Abs(Vector3.Dot(this.transform.forward, grabbedObjectIn.transform.up));
    float num3 = Mathf.Abs(Vector3.Dot(this.transform.forward, grabbedObjectIn.transform.forward));
    if ((double) num1 > (double) num2)
    {
      possibleAxis0 = grabbedObjectIn.transform.up;
      if ((double) num1 > (double) num3)
      {
        facingPlaneOut = new Plane(grabbedObjectIn.transform.right, grabbedObjectIn.transform.position);
        possibleAxis1 = grabbedObjectIn.transform.forward;
      }
      else
      {
        facingPlaneOut = new Plane(grabbedObjectIn.transform.forward, grabbedObjectIn.transform.position);
        possibleAxis1 = grabbedObjectIn.transform.right;
      }
    }
    else
    {
      possibleAxis0 = grabbedObjectIn.transform.right;
      if ((double) num2 > (double) num3)
      {
        facingPlaneOut = new Plane(grabbedObjectIn.transform.up, grabbedObjectIn.transform.position);
        possibleAxis1 = grabbedObjectIn.transform.forward;
      }
      else
      {
        facingPlaneOut = new Plane(grabbedObjectIn.transform.forward, grabbedObjectIn.transform.position);
        possibleAxis1 = grabbedObjectIn.transform.up;
      }
    }
  }

  private Vector3 GetFinalAxis(
    Plane facingPlaneIn,
    GameObject grabbedObjectIn,
    Vector3 possibleAxis0,
    Vector3 possibleAxis1)
  {
    Vector3 vector3 = Vector3.right;
    Ray ray = new Ray(this.transform.position, this.transform.forward);
    float enter;
    if (facingPlaneIn.Raycast(ray, out enter))
    {
      Vector3 normalized = (ray.GetPoint(enter) - grabbedObjectIn.transform.position).normalized;
      vector3 = (double) Mathf.Abs(Vector3.Dot(possibleAxis0, normalized)) > (double) Mathf.Abs(Vector3.Dot(possibleAxis1, normalized)) ? possibleAxis0 : possibleAxis1;
    }
    return vector3;
  }

  private void StartScrolling(bool counterZFighting)
  {
    this.isScrolling = true;
    Vector3 possibleAxis0;
    Vector3 possibleAxis1;
    this.GetPossibleAxes(this.grabbedObject, out possibleAxis0, out possibleAxis1, out this.facingPlane);
    this.scrollWorldAxis = this.GetFinalAxis(this.facingPlane, this.grabbedObject, possibleAxis0, possibleAxis1);
    Rigidbody component = this.grabbedObject.GetComponent<Rigidbody>();
    if ((bool) (UnityEngine.Object) component)
    {
      this.wasKinematic = component.isKinematic;
      component.isKinematic = true;
    }
    if (counterZFighting)
      this.grabbedObject.transform.position += this.facingPlane.normal * (1f / 1000f);
    this.originalGrabbObjectPosition = this.grabbedObject.transform.position;
    this.mouseOffset = this.GetPointOnScrollAxis().Value - this.originalGrabbObjectPosition;
  }

  private void EndScrolling()
  {
    Rigidbody component = this.grabbedObject.GetComponent<Rigidbody>();
    if ((bool) (UnityEngine.Object) component)
      component.isKinematic = this.wasKinematic;
    this.isScrolling = false;
    this._InvokeOnDroppedEvents(this.grabbedObject.GetComponent<DropTriggerScript>());
  }

  private Vector3 GetPointOnLine(Vector3 p, Vector3 a, Vector3 b) => a + Vector3.Project(p - a, b - a);

  private Vector3? GetPointOnScrollAxis()
  {
    Ray ray = new Ray(this.transform.position, this.transform.forward);
    float enter;
    return this.facingPlane.Raycast(ray, out enter) ? new Vector3?(this.GetPointOnLine(ray.GetPoint(enter), this.originalGrabbObjectPosition, this.originalGrabbObjectPosition + this.scrollWorldAxis)) : new Vector3?();
  }

  private void UpdateScrollThing()
  {
    if (!this.isScrolling)
      return;
    Vector3? pointOnScrollAxis = this.GetPointOnScrollAxis();
    if (!pointOnScrollAxis.HasValue)
      return;
    this.grabbedObject.transform.position = pointOnScrollAxis.Value - this.mouseOffset;
  }

  public void OnOwnershipRequest(PhotonView targetView, Photon.Realtime.Player requestingPlayer)
  {
  }

  public void OnOwnershipTransfered(PhotonView targetView, Photon.Realtime.Player previousOwner)
  {
    targetView.GetComponent<DropTriggerScript>()?.Photon_OnOwnershipTransfered(previousOwner);
    FollowMouseThroughForces component = targetView.GetComponent<FollowMouseThroughForces>();
    if (!(bool) (UnityEngine.Object) component || targetView.IsMine)
      return;
    component.SetOnOff(false);
  }

  public void OnOwnershipTransferFailed(PhotonView targetView, Photon.Realtime.Player senderOfFailedRequest) => targetView.GetComponent<DropTriggerScript>()?.Photon_OnOwnershipTransferFailed(senderOfFailedRequest);

  private struct PortalAndIndex
  {
    public int PortalIndex;
    public int BackRayIndex;
  }

  [BurstCompile]
  private struct FilterRayHitsJob : IJobParallelForFilter
  {
    [ReadOnly]
    public NativeArray<RaycastHit> PrelimResults;

    public bool Execute(int index) => this.PrelimResults[index].point != Vector3.zero;
  }

  [BurstCompile]
  private struct ConstructMainRaysJob : IJobParallelFor
  {
    [ReadOnly]
    public int LayerMask;
    [ReadOnly]
    public Vector3 Origin;
    [ReadOnly]
    public NativeArray<int> FilteredIndices;
    [ReadOnly]
    public NativeArray<RaycastHit> UnfilteredResults;
    [WriteOnly]
    public NativeArray<RaycastCommand> MainRays;

    public void Execute(int i)
    {
      int filteredIndex = this.FilteredIndices[i];
      this.MainRays[i] = new RaycastCommand(this.Origin, this.UnfilteredResults[filteredIndex].point - this.Origin, float.PositiveInfinity, this.LayerMask);
    }
  }
}

SaveAndCheckpointManager#

Commands mentioned: ao

using Photon.Pun;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering.PostProcessing;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class SaveAndCheckpointManager : MonoBehaviour
{
  private const string SaveFolderName = "Clouds";
  private const string SaveGameFilename = "Avocado";
  private const string UnlockedLevelsFilename = "ExitSignPerson";
  private const string PlayerActionTrackingFilename = "DrPierceARealDr";
  private const string AchievementTrackingFilename = "SaturdayBeans";
  private const string ChallengeModeFilename = "RysanShipping";
  private const string MiniChallengeModeFilename = "MiniRysanShipping";
  private const string MultiplayerSaveDataFilename = "LoagieSonic";
  public bool startTestTimer;
  public float testTimer;
  public float savingIconTimerBase;
  public float savingIconTimer;
  public AchievementTracker AchievementTracker;
  public PlayerActionTracker PlayerActionTracker;
  public AchievementDefinition WinGameAchievement;
  public AchievementDefinition WinGame60Achievement;
  public AchievementDefinition WinGame30Achievement;
  public AchievementDefinition BiggestFanAchievement;
  public bool showSaveIconWhileSaving = true;
  public double elapsedTimeSinceStart;
  private bool isCountingPlayTimeOverall;
  private bool isCountingPlayTimeThisScene;
  [HideInInspector]
  public float TimeSinceLastCheckpoint;
  [HideInInspector]
  public bool HitCheckpointThisLevel;
  [HideInInspector]
  public GameObject MyPauseMenu;
  [HideInInspector]
  public bool freezeSpeedRunTimer;
  private string saveFolder;
  public LevelInfo LevelInfo;
  private LevelUnlockState LevelUnlockStatus = new LevelUnlockState(-1);
  private PlayerActionSaveData playerActionSaveData = new PlayerActionSaveData();
  private AchievementSaveData achievementSaveData = new AchievementSaveData();
  private ChallengeModeSaveData challengeModeSaveData = new ChallengeModeSaveData();
  private MiniChallengeModeSaveData miniChallengeModeSaveData = new MiniChallengeModeSaveData();
  private MultiplayerSaveData multiplayerSaveData = new MultiplayerSaveData();
  private readonly KeystrokeTracker tracker = new KeystrokeTracker()
  {
    KeyCodes = new KeyCode[2]{ KeyCode.A, KeyCode.O }
  };
  private List<SaveAndCheckpointManager.RoomCheckpointSyncers> checkpointSyncerTracker = new List<SaveAndCheckpointManager.RoomCheckpointSyncers>();
  private SaveGameState? lastSaveGameState;
  private string resetMiniChallenge;
  private List<string> unlockedLevels = new List<string>();
  public static int XORKey = 129;
  private int[] realLevelsBuildsIndices;
  [NonSerialized]
  public PlayerActionChangedEvent PlayerActionChanged;

  public void StartPlayTimeTimer()
  {
    this.isCountingPlayTimeOverall = true;
    this.elapsedTimeSinceStart = 0.0;
  }

  public void StopPlayTimeTimer() => this.isCountingPlayTimeOverall = false;

  public void CalculatePlayTime()
  {
    if (this.isCountingPlayTimeOverall && this.isCountingPlayTimeThisScene)
    {
      if (this.elapsedTimeSinceStart < 3600.0)
        this.OnGrantAchievement(this.WinGame60Achievement);
      if (this.elapsedTimeSinceStart < 1800.0)
        this.OnGrantAchievement(this.WinGame30Achievement);
    }
    this.StopPlayTimeTimer();
  }

  private string GetSaveFolder()
  {
    if (this.saveFolder == null)
    {
      this.saveFolder = Path.Combine(Application.persistentDataPath, "Clouds");
      try
      {
        Directory.CreateDirectory(this.saveFolder);
      }
      catch (Exception ex)
      {
      }
    }
    return this.saveFolder;
  }

  private void OnEnable() => SceneManager.sceneLoaded += new UnityAction<Scene, LoadSceneMode>(this.OnSceneLoaded);

  private void OnDisable() => SceneManager.sceneLoaded -= new UnityAction<Scene, LoadSceneMode>(this.OnSceneLoaded);

  private void CheckWinGame()
  {
    if (!this.playerActionSaveData.HasCompletedGame)
      return;
    this.OnGrantAchievement(this.WinGameAchievement);
  }

  private void _ReadInitialPlayerSaveData()
  {
    this._ReadLevelUnlocked();
    this._LoadPlayerActions();
    this._LoadAchievements();
    this._LoadChallengeModeStats();
    this._LoadMiniChallengeModeStats();
    this._LoadMultiplayerSaveData();
  }

  private void Awake()
  {
    if (!Debug.isDebugBuild)
      return;
    HashSet<string> stringSet = new HashSet<string>();
    foreach (CheckPoint checkPoint in UnityEngine.Object.FindObjectsOfType<CheckPoint>())
    {
      stringSet.Contains(checkPoint.GetName());
      stringSet.Add(checkPoint.GetName());
    }
  }

  private void Start()
  {
    this.achievementSaveData.LoadSteamworksOnStart();
    this.MyPauseMenu = GameObject.Find("UI_PAUSE_MENU");
  }

  private void _ReadLevelUnlocked()
  {
    if (!File.Exists(Path.Combine(this.GetSaveFolder(), "ExitSignPerson")))
      return;
    this.LevelUnlockStatus.Load(new BinaryReader((Stream) this._ReadStreamFromFile("ExitSignPerson")));
    int levelIndex = this.LevelInfo.GetLevelIndex(this.LevelUnlockStatus.UnlockLevelName);
    if (levelIndex <= this.LevelUnlockStatus.MaxUnlockedLevel)
      return;
    this.LevelUnlockStatus.MaxUnlockedLevel = levelIndex;
  }

  private void _SetLevelUnlocked()
  {
    string currentSceneSaveName = this.LevelInfo.GetCurrentSceneSaveName();
    if (currentSceneSaveName.Length <= 0)
      return;
    int levelIndex = this.LevelInfo.GetLevelIndex(currentSceneSaveName);
    if (levelIndex <= this.LevelUnlockStatus.MaxUnlockedLevel)
      return;
    this.LevelUnlockStatus.MaxUnlockedLevel = levelIndex;
    this.LevelUnlockStatus.UnlockLevelName = currentSceneSaveName;
    MemoryStream stream = new MemoryStream();
    this.LevelUnlockStatus.Save(new BinaryWriter((Stream) stream));
    this._SaveStreamToFile(stream, "ExitSignPerson");
  }

  public bool ShouldShowSpeedRunTimer() => this.IsInSpeedRun() || this.freezeSpeedRunTimer;

  public bool IsInSpeedRun() => this.isCountingPlayTimeOverall && this.isCountingPlayTimeThisScene && (!GameManager.GM.GetComponent<MiniChallengeMode>().MiniChallengeModeEnabled && !GameManager.GM.GetComponent<CommentaryMode>().CommentaryModeEnabled) && !GameManager.GM.GetComponent<MultiplayerMode>().MultiplayerEnabled;

  private void Update()
  {
    if (this.isCountingPlayTimeOverall && this.isCountingPlayTimeThisScene)
      this.elapsedTimeSinceStart += (double) Time.deltaTime;
    if ((double) this.savingIconTimer > 0.0)
      this.savingIconTimer -= Time.deltaTime;
    else if ((double) this.savingIconTimer <= 0.0 && (double) this.savingIconTimer > -100.0)
    {
      if ((UnityEngine.Object) GameObject.Find("UI_PAUSE_MENU") != (UnityEngine.Object) null)
        GameObject.Find("UI_PAUSE_MENU").transform.Find("Canvas").gameObject.transform.Find("SavingIcon").gameObject.GetComponent<Image>().enabled = false;
      this.savingIconTimer = -1000f;
    }
    if (GameManager.GM.enableDebugFunctions && this.tracker.Check())
      AmbientOcclusion.ModeOverride = AmbientOcclusion.ModeOverride != AmbientOcclusionMode.ScalableAmbientObscurance ? AmbientOcclusionMode.ScalableAmbientObscurance : AmbientOcclusionMode.MultiScaleVolumetricObscurance;
    this.TimeSinceLastCheckpoint += Time.deltaTime;
  }

  private void _GrabPlayerTransform(ref SaveGameState state)
  {
    if ((UnityEngine.Object) GameManager.GM.player == (UnityEngine.Object) null)
      return;
    state.PlayerPosition = GameManager.GM.player.transform.position;
    state.PlayerRotation = GameManager.GM.player.transform.rotation;
    state.PlayerScale = GameManager.GM.player.transform.localScale;
    this._GrabPlayerMovementValues(ref state);
  }

  private void _GrabPlayerMovementValues(ref SaveGameState state) => GameManager.GM.player.GetComponent<PlayerResizer>().Poke();

  private void _SaveGame(CheckPoint checkpoint)
  {
    MemoryStream stream = new MemoryStream();
    this._SaveGameHelper(new BinaryWriter((Stream) stream), checkpoint);
    stream.Seek(0L, SeekOrigin.Begin);
    if (!GameManager.GM.GetComponent<MultiplayerMode>().MultiplayerEnabled && !GameManager.GM.GetComponent<ChallengeMode>().ChallengeModeEnabled && (!GameManager.GM.GetComponent<CommentaryMode>().CommentaryModeEnabled && !GameManager.GM.GetComponent<MiniChallengeMode>().MiniChallengeModeEnabled))
      this._SaveStreamToFile(stream, "Avocado");
    this.TimeSinceLastCheckpoint = 0.0f;
    this.HitCheckpointThisLevel = true;
    if (!((UnityEngine.Object) this.MyPauseMenu != (UnityEngine.Object) null))
      return;
    this.MyPauseMenu.transform.Find("Canvas").gameObject.transform.Find("Pause Menu").gameObject.GetComponent<PauseMenu>().SetTimeSinceLastCheckpoint();
  }

  public void TriggerSaveIcon()
  {
    GameObject.Find("UI_PAUSE_MENU").transform.Find("Canvas").gameObject.transform.Find("SavingIcon").gameObject.GetComponent<Image>().enabled = true;
    this.savingIconTimer = this.savingIconTimerBase;
  }

  private void _SaveGameHelper(BinaryWriter writer, CheckPoint checkpoint)
  {
    SaveGameState state = new SaveGameState();
    state.LevelName = this.LevelInfo.GetCurrentSceneSaveName();
    state.CheckpointName = (bool) (UnityEngine.Object) checkpoint ? checkpoint.GetName() : string.Empty;
    this._GrabPlayerTransform(ref state);
    state.Save(writer);
    this.lastSaveGameState = new SaveGameState?(state);
    if (!this.showSaveIconWhileSaving || GameManager.GM.GetComponent<ChallengeMode>().ChallengeModeEnabled || (GameManager.GM.GetComponent<CommentaryMode>().CommentaryModeEnabled || GameManager.GM.GetComponent<MiniChallengeMode>().MiniChallengeModeEnabled) || GameManager.GM.GetComponent<MultiplayerMode>().MultiplayerEnabled)
      return;
    this.TriggerSaveIcon();
  }

  private void _RestoreSaveGameState(SaveGameState loadedGame)
  {
    if (PhotonNetwork.IsConnected)
      return;
    string currentSceneSaveName = this.LevelInfo.GetCurrentSceneSaveName();
    if (loadedGame.LevelName != currentSceneSaveName)
      return;
    CheckPoint checkPoint1 = (CheckPoint) null;
    if (loadedGame.CheckpointName != null)
    {
      foreach (CheckPoint checkPoint2 in UnityEngine.Object.FindObjectsOfType<CheckPoint>())
      {
        if (checkPoint2.GetName() == loadedGame.CheckpointName)
        {
          checkPoint1 = checkPoint2;
          break;
        }
      }
      if (!(bool) (UnityEngine.Object) checkPoint1)
      {
        int length = loadedGame.CheckpointName.Length;
      }
    }
    GameObject player = GameManager.GM.player;
    if (loadedGame.HasFullInfo)
    {
      player.transform.position = loadedGame.PlayerPosition;
      player.transform.rotation = loadedGame.PlayerRotation;
      player.transform.localScale = loadedGame.PlayerScale;
      player.GetComponent<PlayerResizer>().Poke();
    }
    else if ((bool) (UnityEngine.Object) checkPoint1)
    {
      player.transform.position = checkPoint1.transform.position;
      player.transform.rotation = checkPoint1.transform.rotation;
      player.transform.localScale = checkPoint1.transform.lossyScale;
      player.GetComponent<PlayerResizer>().Poke();
    }
    if (!(bool) (UnityEngine.Object) checkPoint1)
      return;
    this._TriggerPreviousCheckpointSyncers(checkPoint1.transform);
  }

  private void _RestorePositionAfterResetMiniChallenge(string miniChallengeCheckPointName)
  {
    MiniChallenge miniChallenge1 = (MiniChallenge) null;
    if (miniChallengeCheckPointName != null)
    {
      foreach (MiniChallenge miniChallenge2 in UnityEngine.Object.FindObjectsOfType<MiniChallenge>())
      {
        if ((bool) (UnityEngine.Object) miniChallenge2.Data && miniChallenge2.Data.name == miniChallengeCheckPointName)
        {
          miniChallenge1 = miniChallenge2;
          break;
        }
      }
      if (!(bool) (UnityEngine.Object) miniChallenge1)
      {
        int length = miniChallengeCheckPointName.Length;
      }
    }
    GameObject player = GameManager.GM.player;
    player.transform.position = miniChallenge1.ResetPoint.transform.position;
    player.transform.rotation = miniChallenge1.ResetPoint.transform.rotation;
    player.transform.localScale = miniChallenge1.ResetPoint.transform.lossyScale;
    player.GetComponent<PlayerResizer>().Poke();
    this._TriggerPreviousCheckpointSyncers(miniChallenge1.ResetPoint);
    this.GetComponent<MiniChallengeMode>().MiniChallengeToResetTo = miniChallenge1;
  }

  private void _TriggerPreviousCheckpointSyncers(Transform checkpoint)
  {
    RoomOrder objectOfType = UnityEngine.Object.FindObjectOfType<RoomOrder>();
    if (!(bool) (UnityEngine.Object) objectOfType)
      return;
    int roomIndex = objectOfType.GetRoomIndex(checkpoint.root);
    if (roomIndex == -1)
      return;
    foreach (SaveAndCheckpointManager.RoomCheckpointSyncers checkpointSyncers in this.checkpointSyncerTracker)
    {
      if (objectOfType.GetRoomIndex(checkpointSyncers.Room) < roomIndex)
      {
        foreach (MOSTTriggerBase syncer in checkpointSyncers.Syncers)
          syncer.Trigger();
      }
    }
  }

  private void GatherTopLevelCheckpointSyncers()
  {
    this.checkpointSyncerTracker.Clear();
    foreach (MOSTTriggerCheckpointSyncer checkpointSyncer in UnityEngine.Object.FindObjectsOfType<MOSTTriggerCheckpointSyncer>())
    {
      Transform root = checkpointSyncer.transform.root;
      SaveAndCheckpointManager.RoomCheckpointSyncers checkpointSyncers = this.checkpointSyncerTracker.Find((Predicate<SaveAndCheckpointManager.RoomCheckpointSyncers>) (room => (UnityEngine.Object) room.Room == (UnityEngine.Object) root));
      if (checkpointSyncers == null)
      {
        checkpointSyncers = new SaveAndCheckpointManager.RoomCheckpointSyncers()
        {
          Room = root,
          Syncers = new List<MOSTTriggerCheckpointSyncer>()
        };
        this.checkpointSyncerTracker.Add(checkpointSyncers);
      }
      checkpointSyncers.Syncers.Add(checkpointSyncer);
    }
    RoomOrder roomOrder = UnityEngine.Object.FindObjectOfType<RoomOrder>();
    if ((bool) (UnityEngine.Object) roomOrder)
      this.checkpointSyncerTracker.Sort((Comparison<SaveAndCheckpointManager.RoomCheckpointSyncers>) ((x, y) => Array.IndexOf<Transform>(roomOrder.TopLevelRoomOrder, x.Room).CompareTo(Array.IndexOf<Transform>(roomOrder.TopLevelRoomOrder, y.Room))));
    else
      this.LevelInfo.DoesCurrentLevelSupportSaves();
  }

  private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
  {
    this._ReadInitialPlayerSaveData();
    this.CheckWinGame();
    this.GatherTopLevelCheckpointSyncers();
    int num = scene.isLoaded ? 1 : 0;
    bool flag = this.LevelInfo.DoesCurrentLevelSupportSaves();
    this.isCountingPlayTimeThisScene = flag;
    SaveGameState? nullable = new SaveGameState?();
    if (flag)
    {
      MovePlayerHereOnStart[] objectsOfType = UnityEngine.Object.FindObjectsOfType<MovePlayerHereOnStart>();
      foreach (Component component in objectsOfType)
        component.gameObject.SetActive(false);
      if (!string.IsNullOrEmpty(this.resetMiniChallenge) && this.GetComponent<MiniChallengeMode>().MiniChallengeModeEnabled)
      {
        nullable = new SaveGameState?(this.lastSaveGameState.Value);
        this._RestorePositionAfterResetMiniChallenge(this.resetMiniChallenge);
        this.resetMiniChallenge = (string) null;
      }
      else if (this.lastSaveGameState.HasValue)
      {
        nullable = new SaveGameState?(this.lastSaveGameState.Value);
        this._RestoreSaveGameState(this.lastSaveGameState.Value);
      }
      else if (GameManager.GM.SaveGameStateHandoff.HasValue)
      {
        nullable = new SaveGameState?(GameManager.GM.SaveGameStateHandoff.Value);
        this._RestoreSaveGameState(GameManager.GM.SaveGameStateHandoff.Value);
      }
      else if (objectsOfType.Length != 0)
        objectsOfType[0].MoveThePlayerManually();
      GameManager.GM.SaveGameStateHandoff = new SaveGameState?();
      this._SetLevelUnlocked();
    }
    this.lastSaveGameState = nullable;
    if (flag && !this.lastSaveGameState.HasValue)
      this._SaveGame((CheckPoint) null);
    this.TimeSinceLastCheckpoint = 0.0f;
    this.HitCheckpointThisLevel = false;
    this.MyPauseMenu = GameObject.Find("UI_PAUSE_MENU");
    this.freezeSpeedRunTimer = false;
  }

  public void EnteredCheckpoint(CheckPoint checkpoint) => this._SaveGame(checkpoint);

  public void FreezeSpeedRunTimer()
  {
    GameObject.Find("UI_PAUSE_MENU").transform.Find("Canvas").transform.Find("Pause Menu").gameObject.GetComponent<PauseMenu>().UpdateFinalTimeTranslation();
    this.freezeSpeedRunTimer = true;
  }

  public void RestartLevel()
  {
    this.lastSaveGameState = new SaveGameState?();
    this.resetMiniChallenge = (string) null;
    this.GetComponent<ChallengeMode>().SummaryScreenStatus = 0;
    GameManager.GM.GetComponent<MiniChallengeMode>().TurnOffUI();
    SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex, LoadSceneMode.Single);
  }

  public void ResetMiniChallenge(string miniChallengeName)
  {
    this.resetMiniChallenge = miniChallengeName;
    SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex, LoadSceneMode.Single);
  }

  public void ResetToLastCheckpoint()
  {
    if (MultiplayerHelper.InMultiplayerMatch())
    {
      if (!this.lastSaveGameState.HasValue || this.lastSaveGameState.Value.CheckpointName == null || !MultiplayerHelper.IsMine(GameManager.GM.player))
        return;
      this._RestoreSaveGameState(this.lastSaveGameState.Value);
    }
    else
    {
      if (!this.lastSaveGameState.HasValue)
        return;
      GameObject gameObject = GameObject.Find("UI_PAUSE_MENU");
      if ((bool) (UnityEngine.Object) gameObject)
        gameObject.transform.Find("Canvas").gameObject.transform.Find("ResettingToCheckpoint").gameObject.GetComponent<Text>().enabled = true;
      SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex, LoadSceneMode.Single);
    }
  }

  public bool HasLastCheckpoint() => this.lastSaveGameState.HasValue;

  public void ManuallyTriggerPreviousCheckpointSyncers(CheckPoint checkPoint)
  {
    CheckPoint[] objectsOfType = UnityEngine.Object.FindObjectsOfType<CheckPoint>();
    RoomOrder roomOrder = UnityEngine.Object.FindObjectOfType<RoomOrder>();
    if (!(bool) (UnityEngine.Object) roomOrder)
      return;
    Array.Sort<CheckPoint>(objectsOfType, (Comparison<CheckPoint>) ((x, y) => Array.IndexOf<Transform>(roomOrder.TopLevelRoomOrder, x.transform.root).CompareTo(Array.IndexOf<Transform>(roomOrder.TopLevelRoomOrder, y.transform.root))));
    int index = Array.IndexOf<CheckPoint>(objectsOfType, checkPoint);
    if (index == -1)
      return;
    this._TriggerPreviousCheckpointSyncers(objectsOfType[index].transform);
  }

  public void TeleportToCheckpointIndexDebug(int index)
  {
    CheckPoint[] objectsOfType = UnityEngine.Object.FindObjectsOfType<CheckPoint>();
    RoomOrder roomOrder = UnityEngine.Object.FindObjectOfType<RoomOrder>();
    if (!(bool) (UnityEngine.Object) roomOrder)
      return;
    Array.Sort<CheckPoint>(objectsOfType, (Comparison<CheckPoint>) ((x, y) => Array.IndexOf<Transform>(roomOrder.TopLevelRoomOrder, x.transform.root).CompareTo(Array.IndexOf<Transform>(roomOrder.TopLevelRoomOrder, y.transform.root))));
    if (index >= objectsOfType.Length)
      return;
    this.TeleportToCheckpoint(objectsOfType[index]);
    this._TriggerPreviousCheckpointSyncers(objectsOfType[index].transform);
  }

  public void LoadToCheckpoint(SaveGameState state)
  {
    this.lastSaveGameState = new SaveGameState?(state);
    this.StartCoroutine(LevelLoadHelper.LoadSceneAsync(SceneManager.GetActiveScene().path, true, new SaveGameState?()));
  }

  public void TeleportToCheckpoint(CheckPoint checkpoint)
  {
    GameManager.GM.player.transform.position = checkpoint.transform.position;
    GameManager.GM.player.transform.rotation = checkpoint.transform.rotation;
    GameManager.GM.player.transform.localScale = checkpoint.transform.lossyScale;
  }

  public bool CanContinue() => File.Exists(Path.Combine(this.GetSaveFolder(), "Avocado"));

  public void Continue()
  {
    BinaryReader reader = new BinaryReader((Stream) this._ReadStreamFromFile("Avocado"));
    SaveGameState saveGameState = new SaveGameState();
    saveGameState.Load(reader);
    this.StartCoroutine(LevelLoadHelper.LoadSceneAsync(this.LevelInfo.GetScenePathFromSaveName(saveGameState.LevelName), false, new SaveGameState?(saveGameState)));
  }

  public bool CanViewCredits() => this.LevelUnlockStatus.HasCompletedGame;

  public void UnlockLevel(string scenePath)
  {
  }

  public void OnGameCompleted()
  {
    this.LevelUnlockStatus.HasCompletedGame = true;
    MemoryStream stream = new MemoryStream();
    this.LevelUnlockStatus.Save(new BinaryWriter((Stream) stream));
    this._SaveStreamToFile(stream, "ExitSignPerson");
    this.playerActionSaveData.HasCompletedGame = true;
    this._SavePlayerActions();
    if (!this.GetComponent<CommentaryMode>().CommentaryModeEnabled)
      return;
    this.OnGrantAchievement(this.BiggestFanAchievement);
  }

  public static void XOREncryptDecrypt(byte[] dataToEncrypt)
  {
    for (int index = 0; index < dataToEncrypt.Length; ++index)
      dataToEncrypt[index] = (byte) ((uint) dataToEncrypt[index] ^ (uint) SaveAndCheckpointManager.XORKey);
  }

  private void _SaveStreamToFile(MemoryStream stream, string fileTurd)
  {
    string path = Path.Combine(this.GetSaveFolder(), fileTurd);
    try
    {
      byte[] array = stream.ToArray();
      SaveAndCheckpointManager.XOREncryptDecrypt(array);
      File.WriteAllBytes(path, array);
    }
    catch (Exception ex)
    {
    }
  }

  private MemoryStream _ReadStreamFromFile(string fileTurd)
  {
    string path = Path.Combine(this.GetSaveFolder(), fileTurd);
    try
    {
      byte[] numArray = File.ReadAllBytes(path);
      SaveAndCheckpointManager.XOREncryptDecrypt(numArray);
      return new MemoryStream(numArray);
    }
    catch (Exception ex)
    {
      return (MemoryStream) null;
    }
  }

  private void _DeleteFile(string fileTurd)
  {
    string path = Path.Combine(this.GetSaveFolder(), fileTurd);
    try
    {
      File.Delete(path);
    }
    catch (Exception ex)
    {
    }
  }

  public void DeleteAllSaves() => this._DeleteFile("Avocado");

  public void DeleteUnlockedLevels() => this._DeleteFile("ExitSignPerson");

  public void DeletePlayerActions()
  {
    this.playerActionSaveData.DeleteAllPlayerActions();
    this._SavePlayerActions();
  }

  public void DeleteLocalAchievements()
  {
    this.achievementSaveData.DeleteAllAchievements();
    this._SaveAchievements();
  }

  public void DeleteMultiplayerSaveData()
  {
    this.multiplayerSaveData.DeleteAllCosmeticsAndDreamPoints();
    this._SaveMultiplayerData();
  }

  public void UnlockAll()
  {
    this.LevelUnlockStatus.HasCompletedGame = true;
    this.LevelUnlockStatus.MaxUnlockedLevel = 9;
    MemoryStream stream = new MemoryStream();
    this.LevelUnlockStatus.Save(new BinaryWriter((Stream) stream));
    this._SaveStreamToFile(stream, "ExitSignPerson");
    Debug.Log((object) "All levels unlocked.");
    foreach (AchievementDefinition allAchievement in this.AchievementTracker.AllAchievements)
      this.DebugSetAchievement(allAchievement, true);
    Debug.Log((object) "All achievements unlocked.");
    foreach (ActionAndItemNames uniqueObjectCounter in this.PlayerActionTracker.UniqueObjectCounters)
    {
      foreach (string objectName in uniqueObjectCounter.ObjectNames)
        this.OnPlayerAction_Debug(uniqueObjectCounter.Action, objectName, true);
    }
    Debug.Log((object) "All player actions unlocked.");
  }

  public void StartSpecificLevel(string levelSaveName, int? debugLoadingScreen)
  {
    this.lastSaveGameState = new SaveGameState?();
    this.resetMiniChallenge = (string) null;
    this.StartCoroutine(LevelLoadHelper.LoadSceneAsync(this.LevelInfo.GetScenePathFromSaveName(levelSaveName), false, new SaveGameState?(), debugLoadingScreen));
  }

  public void DebugReloadLevelWithLoadingScreen(int loadingScreen)
  {
    this.lastSaveGameState = new SaveGameState?();
    this.resetMiniChallenge = (string) null;
    this.StartCoroutine(LevelLoadHelper.LoadSceneAsync(SceneManager.GetActiveScene().path, false, new SaveGameState?(), new int?(loadingScreen)));
  }

  private void _FillInBuildIndices()
  {
    if (this.realLevelsBuildsIndices != null)
      return;
    this.realLevelsBuildsIndices = new int[this.LevelInfo.RealLevels.Length];
    for (int index = 0; index < this.LevelInfo.RealLevels.Length; ++index)
      this.realLevelsBuildsIndices[index] = SceneUtility.GetBuildIndexByScenePath(this.LevelInfo.RealLevels[index].Scene.ScenePath);
  }

  public List<string> GetUnlockedLevelList()
  {
    this._FillInBuildIndices();
    List<string> stringList = new List<string>();
    int maxUnlockedLevel = this.LevelUnlockStatus.MaxUnlockedLevel;
    for (int index = 0; index < this.LevelInfo.RealLevels.Length && index <= maxUnlockedLevel; ++index)
    {
      if (this.LevelInfo.RealLevels[index].IsActualLevel && this.realLevelsBuildsIndices[index] != -1)
        stringList.Add(this.LevelInfo.RealLevels[index].Name);
    }
    return stringList;
  }

  public List<string> GetLockedLevelList()
  {
    this._FillInBuildIndices();
    List<string> stringList = new List<string>();
    for (int index = this.LevelUnlockStatus.MaxUnlockedLevel + 1; index < this.LevelInfo.RealLevels.Length; ++index)
    {
      if (this.LevelInfo.RealLevels[index].IsActualLevel && this.realLevelsBuildsIndices[index] != -1)
        stringList.Add(this.LevelInfo.RealLevels[index].Name);
    }
    return stringList;
  }

  public void OnPlayerAction(PlayerActionDefinition action, string name)
  {
    if (this.GetComponent<MultiplayerMode>().MultiplayerEnabled || !this.playerActionSaveData.OnPlayerAction(action, name))
      return;
    this._SavePlayerActions();
    this._EvaluateAchievementsDependingOn(action);
    PlayerActionChangedEvent playerActionChanged = this.PlayerActionChanged;
    if (playerActionChanged == null)
      return;
    playerActionChanged(action);
  }

  public void OnPlayerAction_Debug(PlayerActionDefinition action, string name, bool on)
  {
    if (!this.playerActionSaveData.OnPlayerAction(action, name, on))
      return;
    this._SavePlayerActions();
    this._EvaluateAchievementsDependingOn(action);
    PlayerActionChangedEvent playerActionChanged = this.PlayerActionChanged;
    if (playerActionChanged == null)
      return;
    playerActionChanged(action);
  }

  public bool IsPlayerActionComplete(PlayerActionDefinition action, string name) => !this.GetComponent<MultiplayerMode>().MultiplayerEnabled && this.playerActionSaveData.IsPlayerActionComplete(action, name);

  public int GetCompletedActionCount(PlayerActionDefinition action) => this.GetComponent<MultiplayerMode>().MultiplayerEnabled ? 0 : this.playerActionSaveData.GetCompletedActionCount(action);

  public void GetPlayerActionCompletionStatus(
    PlayerActionDefinition action,
    string canonicalLevelName,
    out int completed,
    out int total,
    out bool anyComplete)
  {
    this.playerActionSaveData.GetPlayerActionCompletionStatus(action, canonicalLevelName, out completed, out total, out anyComplete);
  }

  public SerializedTransform GetSavedTransform(string name, bool createIfNone = false) => this.playerActionSaveData.GetSavedTransform(name, createIfNone);

  public void SavePlayerActions() => this._SavePlayerActions();

  private void _LoadPlayerActions()
  {
    if (File.Exists(Path.Combine(this.GetSaveFolder(), "DrPierceARealDr")))
      this.playerActionSaveData.Load(new BinaryReader((Stream) this._ReadStreamFromFile("DrPierceARealDr")));
    else
      this.playerActionSaveData.Load((BinaryReader) null);
  }

  private void _SavePlayerActions()
  {
    MemoryStream stream = new MemoryStream();
    this.playerActionSaveData.Save(new BinaryWriter((Stream) stream));
    this._SaveStreamToFile(stream, "DrPierceARealDr");
  }

  public void OnGrantAchievement(AchievementDefinition achievement)
  {
    if (!this.achievementSaveData.OnGrantAchievement(achievement))
      return;
    this._SaveAchievements();
  }

  public bool HasAchievement(AchievementDefinition achievement) => this.achievementSaveData.HasAchievement(achievement);

  public void DebugSetAchievement(AchievementDefinition achievement, bool granted)
  {
    if (granted)
      this.OnGrantAchievement(achievement);
    else
      this.achievementSaveData.DebugSetAchievement(achievement, granted);
    this._SaveAchievements();
  }

  private void _LoadAchievements()
  {
    if (File.Exists(Path.Combine(this.GetSaveFolder(), "SaturdayBeans")))
      this.achievementSaveData.Load(new BinaryReader((Stream) this._ReadStreamFromFile("SaturdayBeans")));
    else
      this.achievementSaveData.Load((BinaryReader) null);
  }

  private void _LoadMultiplayerSaveData()
  {
    if (File.Exists(Path.Combine(this.GetSaveFolder(), "LoagieSonic")))
      this.multiplayerSaveData.Load(new BinaryReader((Stream) this._ReadStreamFromFile("LoagieSonic")));
    else
      this.multiplayerSaveData.Load((BinaryReader) null);
  }

  public string GetPreviousCosmeticDataOfType(CosmeticData.Type type) => this.multiplayerSaveData.GetRecentlyChosen(type);

  public void SetPreviousCosmetic(CosmeticData data)
  {
    this.multiplayerSaveData.SetRecentlyChosen(data.type, data.name);
    this._SaveMultiplayerData();
  }

  public int GetDreamPoints() => this.multiplayerSaveData.DreamPoints;

  public void SetDreamPoints(int dreamPoints)
  {
    if (this.multiplayerSaveData.DreamPoints == dreamPoints)
      return;
    this.multiplayerSaveData.DreamPoints = dreamPoints;
    this._SaveMultiplayerData();
  }

  public void UnlockCosmetic(string cosmeticName)
  {
    this.multiplayerSaveData.UnlockCosmetic(cosmeticName);
    this._SaveMultiplayerData();
  }

  public bool IsCosmeticUnlocked(string cosmeticName) => this.multiplayerSaveData.HasCosmetic(cosmeticName);

  public void RegrantAchievedAchievements()
  {
    foreach (AchievementDefinition allAchievement in this.AchievementTracker.AllAchievements)
    {
      if (this.HasAchievement(allAchievement))
        this.OnGrantAchievement(allAchievement);
    }
  }

  private bool IsWorkshopAvailable() => true;

  private void _LoadChallengeModeStats()
  {
    if (File.Exists(Path.Combine(this.GetSaveFolder(), "RysanShipping")))
      this.challengeModeSaveData.Load(new BinaryReader((Stream) this._ReadStreamFromFile("RysanShipping")));
    else
      this.challengeModeSaveData.Load((BinaryReader) null);
  }

  private void _SaveChallengeModeStats()
  {
    MemoryStream stream = new MemoryStream();
    this.challengeModeSaveData.Save(new BinaryWriter((Stream) stream));
    this._SaveStreamToFile(stream, "RysanShipping");
  }

  public PerLevelChallengeModeSaveData GetChallengeModeStatsForLevel(
    string levelSaveName)
  {
    return this.challengeModeSaveData.GetChallengeModeSaveData(levelSaveName);
  }

  public PerLevelChallengeModeSaveData GetChallengeModeStatsForCurrentLevel() => this.challengeModeSaveData.GetChallengeModeSaveData(this.LevelInfo.GetCurrentSceneSaveName());

  public void SetChallengeModeStatsForCurrentLevel(PerLevelChallengeModeSaveData data)
  {
    this.challengeModeSaveData.SetChallengeModeSaveData(this.LevelInfo.GetCurrentSceneSaveName(), data);
    this._SaveChallengeModeStats();
  }

  private void _SaveAchievements()
  {
    MemoryStream stream = new MemoryStream();
    this.achievementSaveData.Save(new BinaryWriter((Stream) stream));
    this._SaveStreamToFile(stream, "SaturdayBeans");
  }

  private void _SaveMultiplayerData()
  {
    MemoryStream stream = new MemoryStream();
    this.multiplayerSaveData.Save(new BinaryWriter((Stream) stream));
    this._SaveStreamToFile(stream, "LoagieSonic");
  }

  private void _EvaluateAchievementsDependingOn(PlayerActionDefinition action)
  {
    foreach (AchievementDefinition allAchievement in this.AchievementTracker.AllAchievements)
    {
      if (this._EvaluateAchievement(allAchievement))
        this.OnGrantAchievement(allAchievement);
    }
  }

  private bool _EvaluateAchievement(AchievementDefinition achievement)
  {
    bool flag1 = false;
    if ((uint) achievement.ActionCountConditions.Length > 0U)
    {
      flag1 = true;
      foreach (ActionCountCondition actionCountCondition in achievement.ActionCountConditions)
      {
        int completedActionCount = this.playerActionSaveData.GetCompletedActionCount(actionCountCondition.Action);
        bool flag2 = false;
        switch (actionCountCondition.Comparison)
        {
          case ActionComparison.GreaterThanOrEqualTo:
            flag2 = completedActionCount >= actionCountCondition.Number;
            break;
          case ActionComparison.AllObjectsSatisfied:
            int uniqueObjectCount = PlayerActionTracker.Instance.GetUniqueObjectCount(actionCountCondition.Action.name);
            flag2 = completedActionCount >= uniqueObjectCount;
            break;
        }
        if (!flag2)
          flag1 = false;
      }
    }
    return flag1;
  }

  public void DeleteChallengeModeStats()
  {
    this._DeleteFile("RysanShipping");
    this._DeleteFile("MiniRysanShipping");
  }

  private void _LoadMiniChallengeModeStats()
  {
    if (File.Exists(Path.Combine(this.GetSaveFolder(), "MiniRysanShipping")))
      this.miniChallengeModeSaveData.Load(new BinaryReader((Stream) this._ReadStreamFromFile("MiniRysanShipping")));
    else
      this.miniChallengeModeSaveData.Load((BinaryReader) null);
  }

  private void _SaveMiniChallengeModeStats()
  {
    MemoryStream stream = new MemoryStream();
    this.miniChallengeModeSaveData.Save(new BinaryWriter((Stream) stream));
    this._SaveStreamToFile(stream, "MiniRysanShipping");
  }

  public void WinMiniChallenge(MiniChallengeData miniChallengeData)
  {
    this.miniChallengeModeSaveData.SetChallengeModeSaveData(this.LevelInfo.GetCurrentSceneSaveName(), miniChallengeData.name);
    this._SaveMiniChallengeModeStats();
  }

  public int GetMiniChallengeWonCount() => this.miniChallengeModeSaveData.GetMiniChallengeWonCount();

  public PerLevelMiniChallengeModeSaveData GetMiniChallengeModeStatsForLevel(
    string levelSaveName)
  {
    return this.miniChallengeModeSaveData.GetChallengeModeSaveData(levelSaveName);
  }

  public PerLevelMiniChallengeModeSaveData GetMiniChallengeModeStatsForCurrentLevel() => this.miniChallengeModeSaveData.GetChallengeModeSaveData(this.LevelInfo.GetCurrentSceneSaveName());

  public void TurnOffNewModesPromptAndSave() => PlayerPrefs.SetInt("NewModesPrompt", 1);

  public void DeleteNewModesPromptSaveStatus() => PlayerPrefs.SetInt("NewModesPrompt", 0);

  private class RoomCheckpointSyncers
  {
    public Transform Room;
    public List<MOSTTriggerCheckpointSyncer> Syncers;
  }
}

ToggleReflection#

Commands mentioned: ref

using UnityEngine;

public class ToggleReflection : MonoBehaviour
{
  public static bool UseMirror = true;
  private KeystrokeTracker tracker = new KeystrokeTracker()
  {
    KeyCodes = new KeyCode[3]
    {
      KeyCode.R,
      KeyCode.E,
      KeyCode.F
    }
  };

  private void Update()
  {
    if (!this.tracker.Check())
      return;
    ToggleReflection.UseMirror = !ToggleReflection.UseMirror;
  }
}