diff --git a/2025/lake/chall_db.py b/2025/lake/chall_db.py new file mode 100644 index 0000000..f2cb77b --- /dev/null +++ b/2025/lake/chall_db.py @@ -0,0 +1,114 @@ +import sqlite3 +import json + +# The raw JSON data provided +json_source = """ +{ + "success": true, + "data": [ + {"id": 123, "type": "dynamic", "name": "drum machine", "value": 100, "solves": 160, "solved_by_me": true, "category": "rev", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 125, "type": "dynamic", "name": "Attack of the Clones", "value": 100, "solves": 173, "solved_by_me": true, "category": "crypto", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 126, "type": "dynamic", "name": "Revenge of the Sith", "value": 100, "solves": 224, "solved_by_me": false, "category": "crypto", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 127, "type": "dynamic", "name": "The Phantom Menace", "value": 100, "solves": 280, "solved_by_me": true, "category": "crypto", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 128, "type": "dynamic", "name": "zipbomb", "value": 100, "solves": 318, "solved_by_me": false, "category": "misc", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 129, "type": "dynamic", "name": "Wordler", "value": 100, "solves": 147, "solved_by_me": true, "category": "misc", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 131, "type": "dynamic", "name": "dilemma", "value": 100, "solves": 131, "solved_by_me": true, "category": "rev", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 133, "type": "dynamic", "name": "Quantum vernam", "value": 100, "solves": 202, "solved_by_me": false, "category": "crypto", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 135, "type": "dynamic", "name": "Another Android Applaketion", "value": 100, "solves": 106, "solved_by_me": true, "category": "rev", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 137, "type": "dynamic", "name": "Guess Flag", "value": 100, "solves": 284, "solved_by_me": true, "category": "crypto", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 138, "type": "dynamic", "name": "Ez Part", "value": 100, "solves": 96, "solved_by_me": true, "category": "crypto", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 140, "type": "dynamic", "name": "gamblecore", "value": 100, "solves": 142, "solved_by_me": true, "category": "web", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 142, "type": "dynamic", "name": "illegal downloading", "value": 100, "solves": 58, "solved_by_me": true, "category": "misc", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 143, "type": "dynamic", "name": "stackception-1", "value": 100, "solves": 123, "solved_by_me": false, "category": "pwn", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 147, "type": "dynamic", "name": "Le Canard du Lac", "value": 100, "solves": 289, "solved_by_me": true, "category": "web", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 130, "type": "dynamic", "name": "MagicAuth", "value": 101, "solves": 55, "solved_by_me": false, "category": "web", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 124, "type": "dynamic", "name": "New Mitigations", "value": 102, "solves": 48, "solved_by_me": false, "category": "pwn", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 144, "type": "dynamic", "name": "stackception-2", "value": 193, "solves": 15, "solved_by_me": false, "category": "pwn", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 132, "type": "dynamic", "name": "A real CTF", "value": 217, "solves": 13, "solved_by_me": false, "category": "rev", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 134, "type": "dynamic", "name": "Unlink THIS!", "value": 304, "solves": 8, "solved_by_me": false, "category": "pwn", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 141, "type": "dynamic", "name": "Pls respond", "value": 356, "solves": 6, "solved_by_me": false, "category": "misc", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"}, + {"id": 139, "type": "dynamic", "name": "still-not-malloc", "value": 457, "solves": 3, "solved_by_me": false, "category": "pwn", "tags": [], "template": "/plugins/dynamic_challenges/assets/view.html", "script": "/plugins/dynamic_challenges/assets/view.js"} + ] +} +""" + +DB_NAME = "ctf_challenges.db" + +def create_database(): + try: + # Load the JSON string into a Python dictionary + data_dict = json.loads(json_source) + challenges = data_dict['data'] + + # Connect to SQLite database (or create it if it doesn't exist) + conn = sqlite3.connect(DB_NAME) + cursor = conn.cursor() + + print(f"Connected to database: {DB_NAME}") + + # Create table + # We store 'tags' as a TEXT field (JSON string) because SQLite doesn't have an ARRAY type. + # We store 'solved_by_me' as INTEGER (0 or 1) because SQLite doesn't have a strict BOOLEAN type. + create_table_query = """ + CREATE TABLE IF NOT EXISTS challenges ( + id INTEGER PRIMARY KEY, + type TEXT, + name TEXT, + value INTEGER, + solves INTEGER, + solved_by_me INTEGER, + category TEXT, + tags TEXT, + template TEXT, + script TEXT + ); + """ + cursor.execute(create_table_query) + print("Table 'challenges' created successfully.") + + # Prepare data for insertion + rows_to_insert = [] + for challenge in challenges: + row = ( + challenge['id'], + challenge['type'], + challenge['name'], + challenge['value'], + challenge['solves'], + 1 if challenge['solved_by_me'] else 0, # Convert bool to int + challenge['category'], + json.dumps(challenge['tags']), # Convert list to JSON string + challenge['template'], + challenge['script'] + ) + rows_to_insert.append(row) + + # Insert data + insert_query = """ + INSERT OR REPLACE INTO challenges + (id, type, name, value, solves, solved_by_me, category, tags, template, script) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """ + + cursor.executemany(insert_query, rows_to_insert) + conn.commit() + print(f"Successfully inserted {cursor.rowcount} rows.") + + # Verification step: Read back first 3 rows + print("\n--- Verifying Data (First 3 Rows) ---") + cursor.execute("SELECT id, name, category, solved_by_me FROM challenges LIMIT 3") + rows = cursor.fetchall() + for row in rows: + print(f"ID: {row[0]}, Name: {row[1]}, Category: {row[2]}, Solved: {bool(row[3])}") + + except sqlite3.Error as e: + print(f"SQLite error: {e}") + except json.JSONDecodeError as e: + print(f"JSON parsing error: {e}") + finally: + if conn: + conn.close() + print("\nDatabase connection closed.") + +if __name__ == "__main__": + create_database() diff --git a/2025/lake/ctf_challenges.db b/2025/lake/ctf_challenges.db new file mode 100644 index 0000000..417f89d Binary files /dev/null and b/2025/lake/ctf_challenges.db differ diff --git a/2025/lake/misc/zipbomb/flag.txt b/2025/lake/misc/zipbomb/flag.txt new file mode 100644 index 0000000..f1392a5 --- /dev/null +++ b/2025/lake/misc/zipbomb/flag.txt @@ -0,0 +1 @@ +EPFL{m4yb3_TH3_r3A1_r4M_15_th3_Fr13nd5_w3_m4d3_410ng_th3_w4y} \ No newline at end of file diff --git a/2025/lake/misc/zipbomb/unpack.py b/2025/lake/misc/zipbomb/unpack.py new file mode 100644 index 0000000..6a3173e --- /dev/null +++ b/2025/lake/misc/zipbomb/unpack.py @@ -0,0 +1,61 @@ +import zipfile +import os +import glob + +def recursive_unzip_random(): + layer = 0 + + while True: + # 1. Find the current zip file in the directory + # We look for any file ending in .zip + zip_files = glob.glob("*.zip") + + if not zip_files: + print("No more zip files found. Extraction complete.") + break + + # Take the first zip found (assuming only one path exists) + current_zip = zip_files[0] + print(f"Layer {layer}: Processing '{current_zip}'...") + + try: + with zipfile.ZipFile(current_zip, 'r') as z: + # Get the list of files inside *before* extracting + file_list = z.namelist() + z.extractall() + + # Remove the zip we just finished processing to keep the folder clean + os.remove(current_zip) + + # 2. Process the extracted files + next_zip_found = False + + for filename in file_list: + # If it's a directory, ignore it + if os.path.isdir(filename): + continue + + # Check extensions to decide what to do + if filename.endswith(".zip"): + # This is the next layer; leave it alone for the next loop iteration + next_zip_found = True + else: + # This is content (text, image, etc.) + # We rename it with a number prefix to preserve the order (000_filename.txt) + # This is crucial if the filenames themselves form a sentence. + if "flag" not in filename: + os.remove(filename) + + + if not next_zip_found: + print("End of chain reached (no nested zip found).") + break + + layer += 1 + + except zipfile.BadZipFile: + print(f"Error: '{current_zip}' is corrupted.") + break + +if __name__ == "__main__": + recursive_unzip_random() diff --git a/2025/lake/rev/drum_machine/main.i64 b/2025/lake/rev/drum_machine/main.i64 index 86dd1c3..c98bd9c 100644 Binary files a/2025/lake/rev/drum_machine/main.i64 and b/2025/lake/rev/drum_machine/main.i64 differ diff --git a/2025/lake/rev/drum_machine/main.id0 b/2025/lake/rev/drum_machine/main.id0 deleted file mode 100644 index 9737885..0000000 Binary files a/2025/lake/rev/drum_machine/main.id0 and /dev/null differ diff --git a/2025/lake/rev/drum_machine/main.id1 b/2025/lake/rev/drum_machine/main.id1 deleted file mode 100644 index 68eb737..0000000 Binary files a/2025/lake/rev/drum_machine/main.id1 and /dev/null differ diff --git a/2025/lake/rev/drum_machine/main.id2 b/2025/lake/rev/drum_machine/main.id2 deleted file mode 100644 index 04b5442..0000000 Binary files a/2025/lake/rev/drum_machine/main.id2 and /dev/null differ diff --git a/2025/lake/rev/drum_machine/main.til b/2025/lake/rev/drum_machine/main.til deleted file mode 100644 index eb47a2e..0000000 Binary files a/2025/lake/rev/drum_machine/main.til and /dev/null differ diff --git a/2025/lake/rev/real_ctf/Assembly-CSharp b/2025/lake/rev/real_ctf/Assembly-CSharp new file mode 100644 index 0000000..7955fcc --- /dev/null +++ b/2025/lake/rev/real_ctf/Assembly-CSharp @@ -0,0 +1,1514 @@ + +// /home/cato/ctf/2025/lake/rev/real_ctf/a_real_ctf_linux/a_real_ctf_Data/Managed/Assembly-CSharp.dll +// Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null +// Global type: +// Architecture: AnyCPU (64-bit preferred) +// Runtime: v4.0.30319 +// Hash algorithm: SHA1 + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using SFB; +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.Networking; +using UnityEngine.UI; + +[assembly: CompilationRelaxations(8)] +[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] +[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] +[assembly: AssemblyVersion("0.0.0.0")] +public class CursorController : Singleton +{ + private bool cursorLocked = true; + + private void Start() + { + LockCursor(); + } + + private void Update() + { + if (Input.GetKeyDown(KeyCode.Escape)) + { + UnlockCursor(); + } + if (!cursorLocked && Input.GetMouseButtonDown(0)) + { + LockCursor(); + } + } + + public void LockCursor() + { + Cursor.lockState = CursorLockMode.Locked; + Cursor.visible = false; + cursorLocked = true; + } + + public void UnlockCursor() + { + Cursor.lockState = CursorLockMode.None; + Cursor.visible = true; + cursorLocked = false; + } +} +public class GameManager : Singleton +{ + public Level level; + + private bool hasFlag; + + public PlayMode playMode { get; private set; } + + public bool HasFlag + { + get + { + return hasFlag; + } + set + { + hasFlag = value; + if (hasFlag) + { + level.spawnArea.gameObject.SetActive(value: true); + level.flagArea.gameObject.SetActive(value: false); + } + else + { + level.spawnArea.gameObject.SetActive(value: false); + level.flagArea.gameObject.SetActive(value: true); + } + } + } + + private void Start() + { + StartGame(); + } + + public void StartGame() + { + playMode = PlayMode.NORMAL; + HasFlag = false; + Singleton.Instance.transform.SetPositionAndRotation(level.spawnArea.transform.position, level.spawnArea.transform.rotation); + Singleton.Instance.EnableControls(); + Singleton.Instance.Reset(); + Singleton.Instance.StartRecording(); + Singleton.Instance.Pause(); + Singleton.Instance.Reset(); + } + + public void EndGame() + { + List list = Singleton.Instance.EndRecording(); + if (list != null) + { + Replay replay = default(Replay); + replay.levelId = level.levelId; + replay.frames = list; + Replay replay2 = replay; + ReplayWriter.SaveReplay(replay2); + ReplayWriter.UploadReplay(replay2); + StartGame(); + } + } + + public void PlayReplay() + { + Singleton.Instance.EndRecording(); + Replay replay = ReplayReader.LoadReplay(); + if (replay.frames.Count != 0) + { + playMode = PlayMode.REPLAY; + Singleton.Instance.DisableControls(); + UnityEngine.Debug.Log(replay.frames.Count); + Singleton.Instance.PlayReplay(replay); + Singleton.Instance.Resume(); + Singleton.Instance.Reset(); + } + } +} +public enum PlayMode +{ + NORMAL, + REPLAY +} +public class HUD : Singleton +{ + private float deltaTime; + + private long startTime; + + private string notification = ""; + + public void Reset() + { + startTime = DateTimeOffset.Now.ToUnixTimeMilliseconds(); + } + + private void Update() + { + deltaTime += (Time.deltaTime - deltaTime) * 0.1f; + } + + private void OnGUI() + { + int width = Screen.width; + int height = Screen.height; + GUIStyle gUIStyle = new GUIStyle(); + Rect position = new Rect(10f, 10f, width, height * 2 / 100); + gUIStyle.alignment = TextAnchor.UpperLeft; + gUIStyle.fontSize = height * 3 / 100; + gUIStyle.normal.textColor = Color.white; + float num = 1f / deltaTime; + string text = $"{num:0.} FPS"; + long num2 = DateTimeOffset.Now.ToUnixTimeMilliseconds() - startTime; + string text2 = $"Time elapsed {(double)num2 / 1000.0:0.}s"; + string text3 = "Keys:"; + text3 += "\n\t'ESCAPE' - UNLOCK CURSOR"; + text3 += "\n\t'ENTER' - START NEW RUN"; + text3 += "\n\t'BACKSPACE' - PLAY REPLAY"; + text3 += "\n\t'U' - UPLOAD REPLAY"; + string text4; + if (Singleton.Instance.playMode == PlayMode.REPLAY) + { + text4 = "REPLAY MODE"; + text3 += "\n\t'SPACE' - PLAY/PAUSE REPLAY"; + } + else + { + text4 = ((!Singleton.Instance.HasFlag) ? "OBJECTIVE : CAPTURE THE FLAG" : "OBJECTIVE : RETURN TO SPAWN"); + text3 += "\n\t'TAB' - END RUN"; + } + string text5 = text + "\n" + text2 + "\n" + text4 + "\n\n" + text3 + "\n\n" + notification; + GUI.Label(position, text5, gUIStyle); + } + + public void SendNotification(string message) + { + notification = message; + } +} +public class Keys : MonoBehaviour +{ + private void Update() + { + if (Input.GetKeyDown(KeyCode.Return)) + { + Singleton.Instance.StartGame(); + } + if (Input.GetKeyDown(KeyCode.Backspace)) + { + Singleton.Instance.PlayReplay(); + } + if (Input.GetKeyDown(KeyCode.U)) + { + ReplayWriter.UploadReplay(ReplayReader.LoadReplay()); + } + if (Singleton.Instance.playMode == PlayMode.NORMAL) + { + if (Input.GetKeyDown(KeyCode.Tab)) + { + Singleton.Instance.EndGame(); + } + } + else if (Singleton.Instance.playMode == PlayMode.REPLAY && Input.GetKeyDown(KeyCode.Space)) + { + Singleton.Instance.Toggle(); + } + } +} +public class Level : MonoBehaviour +{ + public ushort levelId; + + public BoxCollider spawnArea; + + public BoxCollider flagArea; +} +public class Player : Singleton +{ + private PlayerActions playerActions; + + public void Reset() + { + playerActions = PlayerActions.None; + } + + public void EnableControls() + { + GetComponent().enabled = true; + } + + public void DisableControls() + { + GetComponent().enabled = false; + } + + public void PerformAction(PlayerActions action) + { + playerActions |= action; + } + + public PlayerRecord Record() + { + PlayerRecord playerRecord = default(PlayerRecord); + playerRecord.position = base.transform.position; + playerRecord.rotation = base.transform.rotation; + playerRecord.playerActions = playerActions; + PlayerRecord result = playerRecord; + playerActions = PlayerActions.None; + return result; + } + + public void ApplyRecord(PlayerRecord playerRecord) + { + base.transform.position = playerRecord.position; + base.transform.rotation = playerRecord.rotation; + } +} +public struct PlayerRecord +{ + public Vector3 position; + + public Quaternion rotation; + + public PlayerActions playerActions; +} +[Flags] +public enum PlayerActions : byte +{ + None = 0, + Jump = 1, + Forward = 2, + Backward = 4, + Left = 8, + Right = 0x10, + TakeFlag = 0x20, + Collision = 0x80 +} +[RequireComponent(typeof(BoxCollider))] +public class PlayerController : Singleton +{ + [Header("Mouse Settings")] + public float mouseSensitivity = 100f; + + public Transform playerCamera; + + [Header("Movement Settings")] + public float speed = 5f; + + public float gravity = -9.81f; + + public float jumpHeight = 2f; + + [SerializeField] + private LayerMask triggerAreaMask; + + private BoxCollider boxCollider; + + private Vector3 velocity; + + [SerializeField] + private bool isGrounded; + + private float xRotation; + + private Player player; + + private const float skinWidth = 0.01f; + + private void Start() + { + boxCollider = GetComponent(); + player = GetComponent(); + } + + public void UpdatePlayerController(float deltaTime) + { + HandleMouseLook(deltaTime); + HandleMovement(deltaTime); + } + + private void HandleMouseLook(float deltaTime) + { + float num = Input.GetAxis("Mouse X") * mouseSensitivity * deltaTime; + float num2 = Input.GetAxis("Mouse Y") * mouseSensitivity * deltaTime; + xRotation -= num2; + xRotation = Mathf.Clamp(xRotation, -90f, 90f); + playerCamera.localRotation = Quaternion.Euler(xRotation, 0f, 0f); + base.transform.Rotate(Vector3.up * num); + } + + private void HandleMovement(float deltaTime) + { + isGrounded = CheckGrounded(); + float num = Input.GetAxisRaw("Horizontal"); + float num2 = Input.GetAxisRaw("Vertical"); + if (num < 0f) + { + player.PerformAction(PlayerActions.Left); + num = -1f; + } + else if (num > 0f) + { + player.PerformAction(PlayerActions.Right); + num = 1f; + } + if (num2 < 0f) + { + player.PerformAction(PlayerActions.Backward); + num2 = -1f; + } + else if (num2 > 0f) + { + player.PerformAction(PlayerActions.Forward); + num2 = 1f; + } + Vector3 vector = (base.transform.right * num + base.transform.forward * num2).normalized * speed * deltaTime; + if (isGrounded) + { + if (Input.GetButtonDown("Jump")) + { + velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity); + player.PerformAction(PlayerActions.Jump); + } + else + { + velocity.y = 0f; + } + } + else + { + velocity.y += gravity * deltaTime; + } + Vector3 vector2 = Vector3.up * velocity.y * deltaTime; + MoveAndCollide(vector + vector2); + } + + private void MoveAndCollide(Vector3 move) + { + Vector3 position = base.transform.position; + position += Vector3.right * move.x; + position = ResolveCollisions(position); + position += Vector3.up * move.y; + position = ResolveCollisions(position); + position += Vector3.forward * move.z; + position = ResolveCollisions(position); + base.transform.position = position; + } + + private Vector3 ResolveCollisions(Vector3 targetPos) + { + Collider[] array = Physics.OverlapBox(targetPos + boxCollider.center, boxCollider.size * 0.5f, base.transform.rotation); + foreach (Collider collider in array) + { + if (collider == boxCollider) + { + continue; + } + if (collider.isTrigger) + { + OnTriggerEnter(collider); + continue; + } + player.PerformAction(PlayerActions.Collision); + if (Physics.ComputePenetration(boxCollider, targetPos + boxCollider.center, base.transform.rotation, collider, collider.transform.position, collider.transform.rotation, out var direction, out var distance) && distance > 0.0005f) + { + targetPos += direction * (distance + 0.01f); + } + } + return targetPos; + } + + private bool CheckGrounded() + { + float num = 0.05f; + Vector3 vector = base.transform.position + boxCollider.center; + Vector3 vector2 = boxCollider.size * 0.5f - Vector3.up * 0.01f; + int layer = base.gameObject.layer; + return Physics.CheckBox(layerMask: ~((1 << layer) | (int)triggerAreaMask), center: vector + Vector3.down * (vector2.y + num), halfExtents: new Vector3(vector2.x, 0.05f, vector2.z), orientation: base.transform.rotation); + } + + private void OnDrawGizmosSelected() + { + if (!(boxCollider == null)) + { + Gizmos.color = Color.yellow; + Gizmos.matrix = base.transform.localToWorldMatrix; + Gizmos.DrawWireCube(boxCollider.center, boxCollider.size); + } + } + + private void OnTriggerEnter(Collider other) + { + if (!base.enabled) + { + return; + } + if (other == Singleton.Instance.level.spawnArea) + { + if (Singleton.Instance.HasFlag) + { + Singleton.Instance.FinishRun(); + } + } + else if (other == Singleton.Instance.level.flagArea) + { + player.PerformAction(PlayerActions.TakeFlag); + Singleton.Instance.HasFlag = true; + } + } +} +public struct Replay +{ + public const ulong MAGIC = 72848253210177uL; + + public const ushort VERSION = 1; + + public ushort levelId; + + public List frames; +} +public struct FrameRecord +{ + public PlayerRecord playerRecord; +} +public class ReplayPlayer : Singleton +{ + private LinkedList frames; + + private bool running; + + public void PlayReplay(Replay replay) + { + frames = new LinkedList(replay.frames); + } + + public void Resume() + { + running = true; + } + + public void Pause() + { + running = false; + } + + public void Toggle() + { + running = !running; + } + + private void FixedUpdate() + { + if (running) + { + if (frames.Count == 0) + { + Singleton.Instance.StartGame(); + return; + } + FrameRecord value = frames.First.Value; + frames.RemoveFirst(); + Singleton.Instance.ApplyRecord(value.playerRecord); + } + } +} +public class ReplayReader +{ + private ushort levelId; + + private ushort frameCount; + + private List frames; + + public static Replay LoadReplay() + { + Singleton.Instance.UnlockCursor(); + string[] array = StandaloneFileBrowser.OpenFilePanel("Open Replay File", "", "", multiselect: false); + Singleton.Instance.LockCursor(); + if (array.Length == 0 || string.IsNullOrEmpty(array[0])) + { + Replay result = default(Replay); + result.frames = new List(); + return result; + } + string path = array[0]; + ReplayReader replayReader = new ReplayReader(); + using FileStream input = new FileStream(path, FileMode.Open, FileAccess.Read); + using BinaryReader reader = new BinaryReader(input); + replayReader.readHeader(reader); + replayReader.readFrames(reader); + Replay result = default(Replay); + result.levelId = replayReader.levelId; + result.frames = new List(replayReader.frames); + return result; + } + + private void readHeader(BinaryReader reader) + { + if (reader.ReadUInt64() != 72848253210177L) + { + throw new Exception("Invalid replay file: MAGIC mismatch."); + } + ushort num = reader.ReadUInt16(); + if (num != 1) + { + throw new Exception($"Unsupported replay version: {num} (expected {(ushort)1})"); + } + levelId = reader.ReadUInt16(); + frameCount = reader.ReadUInt16(); + } + + private void readFrames(BinaryReader reader) + { + frames = new List(); + for (ushort num = 0; num < frameCount; num = (ushort)(num + 1)) + { + frames.Add(readFrame(reader)); + } + } + + private static FrameRecord readFrame(BinaryReader reader) + { + PlayerRecord playerRecord = readPlayer(reader); + FrameRecord result = default(FrameRecord); + result.playerRecord = playerRecord; + return result; + } + + private static PlayerRecord readPlayer(BinaryReader reader) + { + PlayerRecord result = default(PlayerRecord); + result.position.x = reader.ReadSingle(); + result.position.y = reader.ReadSingle(); + result.position.z = reader.ReadSingle(); + result.rotation.x = reader.ReadSingle(); + result.rotation.y = reader.ReadSingle(); + result.rotation.z = reader.ReadSingle(); + result.rotation.w = reader.ReadSingle(); + result.playerActions = (PlayerActions)reader.ReadByte(); + return result; + } +} +public class ReplayRecorder : Singleton +{ + private List frames; + + private bool runFinished; + + public void StartRecording() + { + frames = new List(); + } + + public List EndRecording() + { + if (frames == null) + { + return null; + } + List result = new List(frames); + frames = null; + return result; + } + + private void FixedUpdate() + { + if (frames != null) + { + runFinished = false; + Singleton.Instance.UpdatePlayerController(Time.fixedDeltaTime); + FrameRecord item = default(FrameRecord); + item.playerRecord = Singleton.Instance.Record(); + frames.Add(item); + if (runFinished) + { + Singleton.Instance.EndGame(); + } + } + } + + public void FinishRun() + { + runFinished = true; + } +} +internal class ReplayWriter +{ + private Replay replay; + + public static string serverURL; + + private ReplayWriter(Replay replay) + { + this.replay = replay; + } + + public static void SaveReplay(Replay replay) + { + Singleton.Instance.UnlockCursor(); + string text = StandaloneFileBrowser.SaveFilePanel("Save Binary File", "", "data", "bin"); + Singleton.Instance.LockCursor(); + if (text.Length != 0 && !string.IsNullOrEmpty(text)) + { + File.WriteAllBytes(text, replayToBytes(replay)); + } + } + + public static async void SendReplay(byte[] bodyRaw) + { + if (string.IsNullOrEmpty(serverURL)) + { + string text = Path.Combine(Application.dataPath, "../server.txt"); + if (!File.Exists(text)) + { + UnityEngine.Debug.LogError("server.txt file not found at " + text); + Singleton.Instance.SendNotification("server.txt file not found at " + text); + return; + } + serverURL = File.ReadAllText(text).Trim(); + } + UnityEngine.Debug.Log("Uploading replay to " + serverURL); + Singleton.Instance.SendNotification("Uploading replay..."); + try + { + string text2 = await PostRequest.SendAsync(serverURL, bodyRaw); + UnityEngine.Debug.Log("Response from server: \n" + text2); + Singleton.Instance.SendNotification("Response from server: \n" + text2); + } + catch (Exception ex) + { + UnityEngine.Debug.LogError("Error: " + ex.Message); + } + } + + public static void UploadReplay(Replay replay) + { + SendReplay(replayToBytes(replay)); + } + + private static byte[] replayToBytes(Replay replay) + { + ReplayWriter replayWriter = new ReplayWriter(replay); + using MemoryStream memoryStream = new MemoryStream(); + using (BinaryWriter writer = new BinaryWriter(memoryStream)) + { + replayWriter.writeHeader(writer); + replayWriter.writeFrames(writer); + } + return memoryStream.ToArray(); + } + + private void writeHeader(BinaryWriter writer) + { + if (replay.frames.Count > 65535) + { + throw new Exception("Too many frames in replay to save!"); + } + writer.Write(72848253210177uL); + writer.Write((ushort)1); + writer.Write(replay.levelId); + writer.Write((ushort)replay.frames.Count); + } + + private void writeFrames(BinaryWriter writer) + { + foreach (FrameRecord frame in replay.frames) + { + writeFrame(writer, frame); + } + } + + private void writeFrame(BinaryWriter writer, FrameRecord frame) + { + writePlayer(writer, frame.playerRecord); + } + + private void writePlayer(BinaryWriter writer, PlayerRecord player) + { + writer.Write(player.position.x); + writer.Write(player.position.y); + writer.Write(player.position.z); + writer.Write(player.rotation.x); + writer.Write(player.rotation.y); + writer.Write(player.rotation.z); + writer.Write(player.rotation.w); + writer.Write((byte)player.playerActions); + } +} +public class PostRequest +{ + public static async Task SendAsync(string url, byte[] bodyRaw) + { + using UnityWebRequest request = new UnityWebRequest(url, "POST"); + request.uploadHandler = new UploadHandlerRaw(bodyRaw); + request.downloadHandler = new DownloadHandlerBuffer(); + UnityWebRequestAsyncOperation operation = request.SendWebRequest(); + while (!operation.isDone) + { + await Task.Yield(); + } + if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError) + { + throw new Exception(request.error); + } + return request.downloadHandler.text; + } +} +public abstract class Singleton : MonoBehaviour where T : MonoBehaviour +{ + private static T _instance; + + public static T Instance + { + get + { + if ((UnityEngine.Object)_instance == (UnityEngine.Object)null) + { + _instance = UnityEngine.Object.FindFirstObjectByType(); + if ((UnityEngine.Object)_instance == (UnityEngine.Object)null) + { + throw new Exception("No instance of " + typeof(T).Name + " found in the scene."); + } + } + return _instance; + } + } + + protected virtual void Awake() + { + if ((UnityEngine.Object)_instance != (UnityEngine.Object)null && _instance != this) + { + UnityEngine.Object.Destroy(base.gameObject); + } + else + { + _instance = this as T; + } + } +} +public class BasicSample : MonoBehaviour +{ + private string _path; + + private void OnGUI() + { + GUI.matrix = Matrix4x4.TRS(s: new Vector3((float)Screen.width / 800f, (float)Screen.height / 600f, 1f), pos: Vector3.zero, q: Quaternion.identity); + GUILayout.Space(20f); + GUILayout.BeginHorizontal(); + GUILayout.Space(20f); + GUILayout.BeginVertical(); + if (GUILayout.Button("Open File")) + { + WriteResult(StandaloneFileBrowser.OpenFilePanel("Open File", "", "", multiselect: false)); + } + GUILayout.Space(5f); + if (GUILayout.Button("Open File Async")) + { + StandaloneFileBrowser.OpenFilePanelAsync("Open File", "", "", multiselect: false, delegate(string[] paths) + { + WriteResult(paths); + }); + } + GUILayout.Space(5f); + if (GUILayout.Button("Open File Multiple")) + { + WriteResult(StandaloneFileBrowser.OpenFilePanel("Open File", "", "", multiselect: true)); + } + GUILayout.Space(5f); + if (GUILayout.Button("Open File Extension")) + { + WriteResult(StandaloneFileBrowser.OpenFilePanel("Open File", "", "txt", multiselect: true)); + } + GUILayout.Space(5f); + if (GUILayout.Button("Open File Directory")) + { + WriteResult(StandaloneFileBrowser.OpenFilePanel("Open File", Application.dataPath, "", multiselect: true)); + } + GUILayout.Space(5f); + if (GUILayout.Button("Open File Filter")) + { + ExtensionFilter[] extensions = new ExtensionFilter[3] + { + new ExtensionFilter("Image Files", "png", "jpg", "jpeg"), + new ExtensionFilter("Sound Files", "mp3", "wav"), + new ExtensionFilter("All Files", "*") + }; + WriteResult(StandaloneFileBrowser.OpenFilePanel("Open File", "", extensions, multiselect: true)); + } + GUILayout.Space(15f); + if (GUILayout.Button("Open Folder")) + { + string[] paths2 = StandaloneFileBrowser.OpenFolderPanel("Select Folder", "", multiselect: true); + WriteResult(paths2); + } + GUILayout.Space(5f); + if (GUILayout.Button("Open Folder Async")) + { + StandaloneFileBrowser.OpenFolderPanelAsync("Select Folder", "", multiselect: true, delegate(string[] paths) + { + WriteResult(paths); + }); + } + GUILayout.Space(5f); + if (GUILayout.Button("Open Folder Directory")) + { + string[] paths3 = StandaloneFileBrowser.OpenFolderPanel("Select Folder", Application.dataPath, multiselect: true); + WriteResult(paths3); + } + GUILayout.Space(15f); + if (GUILayout.Button("Save File")) + { + _path = StandaloneFileBrowser.SaveFilePanel("Save File", "", "", ""); + } + GUILayout.Space(5f); + if (GUILayout.Button("Save File Async")) + { + StandaloneFileBrowser.SaveFilePanelAsync("Save File", "", "", "", delegate(string path) + { + WriteResult(path); + }); + } + GUILayout.Space(5f); + if (GUILayout.Button("Save File Default Name")) + { + _path = StandaloneFileBrowser.SaveFilePanel("Save File", "", "MySaveFile", ""); + } + GUILayout.Space(5f); + if (GUILayout.Button("Save File Default Name Ext")) + { + _path = StandaloneFileBrowser.SaveFilePanel("Save File", "", "MySaveFile", "dat"); + } + GUILayout.Space(5f); + if (GUILayout.Button("Save File Directory")) + { + _path = StandaloneFileBrowser.SaveFilePanel("Save File", Application.dataPath, "", ""); + } + GUILayout.Space(5f); + if (GUILayout.Button("Save File Filter")) + { + ExtensionFilter[] extensions2 = new ExtensionFilter[2] + { + new ExtensionFilter("Binary", "bin"), + new ExtensionFilter("Text", "txt") + }; + _path = StandaloneFileBrowser.SaveFilePanel("Save File", "", "MySaveFile", extensions2); + } + GUILayout.EndVertical(); + GUILayout.Space(20f); + GUILayout.Label(_path); + GUILayout.EndHorizontal(); + } + + public void WriteResult(string[] paths) + { + if (paths.Length != 0) + { + _path = ""; + foreach (string text in paths) + { + _path = _path + text + "\n"; + } + } + } + + public void WriteResult(string path) + { + _path = path; + } +} +[RequireComponent(typeof(Button))] +public class CanvasSampleOpenFileImage : MonoBehaviour, IPointerDownHandler, IEventSystemHandler +{ + public RawImage output; + + public void OnPointerDown(PointerEventData eventData) + { + } + + private void Start() + { + GetComponent