Skip to content

Latest commit

 

History

History
78 lines (58 loc) · 6.35 KB

File metadata and controls

78 lines (58 loc) · 6.35 KB

Shrapnel Overhaul Mod — Developer & Architecture Guide

Welcome under the hood. This document details the technical architecture, zero-alloc network protocol, and compilation guidelines used in the Shrapnel Overhaul Mod (v1.0.0).

If you are a modder or a C# developer, this guide explains how the mod bypasses Unity's standard limitations to achieve massive scale and perfect multiplayer synchronization under Scav game version 6.1.

🏗️ Core Architecture & Performance

The mod replaces standard Unity Instantiate/Destroy calls with a custom engine to achieve zero-GC (Garbage Collection) allocations during steady-state gameplay.

1. Zero-GC Particle Engine (AshParticlePoolManager)

  • Flat-Array Ring Buffer: Pre-allocates up to 8,500 custom particle slots (AshParticlePooled). Uses SetActive(false) for recycling.
  • Frame-Staggered Physics: Particles simulate quadratic drag ($F \propto v^2$) and thermal lift. Expensive Perlin-noise turbulence is staggered (calculated every 3rd frame with a $\times3$ multiplier) to drastically reduce CPU overhead.
  • GPU-Batched Sparks: Small, fast sparks bypass GameObjects entirely. They are routed to Unity's ParticleSystem (ParticlePoolManager) using RenderMode.Stretch. This allows thousands of sparks to render with near-zero CPU cost.
  • Shader Self-Healing: Vanilla Scav has a bug where chunk unloading corrupts Shader.Find references. The mod runs a background routine (HealMaterials) every 60 frames to detect and repair broken materials on the fly.

2. Reflection & Shot Detection (ShotDetectorPatches)

Unity JIT occasionally ignores Harmony Transpilers. To ensure 100% reliable shot detection without breaking the game:

  • Hybrid Polling: Instead of risky IL injection, the mod uses lightweight MonoBehaviour polling to detect rising edges on GunScript.muzzleParticle.isEmitting and TurretScript.didShoot.
  • Dynamic Power Scaling: Weapon power is extracted via Reflection:
    Power = structureDamage * (1 + knockBack/10) * max(1, shotsPerFire) (v1.0.0 fix: Clamped inputs prevent unboxing exceptions, unboxing reflected fields is managed via type-safe converters).

🌐 Network Protocol v4 & Expression JIT Compilation

The mod features a custom, server-authoritative network protocol built via Reflection into Unity.Netcode. It does not require the MP mod to compile or run in singleplayer.

1. Zero-Alloc Expression-Compiled Serialization (New in v1.0.0)

Calling reflected MethodInfo.Invoke() inside hot loops (processing hundreds of shards every frame) introduces severe CPU overhead and generates massive GC garbage because parameters must be boxed into object[] arrays. To solve this, ShrapnelNetSync compiles fast delegate wrappers at startup using LINQ Expressions:

  • Write/Read Delegates: Action<object, T> and Func<object, T> are generated for FastBufferWriter.WriteValueSafe<T> and FastBufferReader.ReadValueSafe<T>.
  • Native Performance: These delegates unbox the boxed writer/reader struct on the heap, and call the JIT-compiled generic methods directly. This matches native C# execution speeds with absolute zero GC allocations on every network tick.

2. The Elimination of MSG_SNAPSHOT

Previous versions sent position updates 10 times a second for every flying shard. Protocol v4 deletes this entirely.

  1. MSG_SPAWN (Reliable, Batched): Server sends initial vectors (Position, Velocity, Rotation, Type, Weight, Heat).
  2. Real Client Physics: Clients create a real Rigidbody2D and CircleCollider2D. The local Unity physics engine handles bouncing and ricochets perfectly.
  3. Damage Gating: On the client, IsServerAuthoritative = false is set. The FSM runs, but collisions with limbs/entities are silently ignored to prevent phantom double-damage.
  4. MSG_STATE (Rest Correction): When a shard stops moving on the server, it sends a final MSG_STATE. The client smoothly snaps the shard to this authoritative resting position (ForceToState).
  5. MSG_DESTROY: Triggers a 150ms visual fade-out on the client to hide any slight positional desync before deletion.

💥 Kinetic Energy Transfer & Geometry Algorithms (v1.0.0)

1. Dynamic Contact Support Checks (New in v1.0.0)

Embedded stuck shards now track the exact surface normal vector they hit (_lastHitNormal). When checking if they should fall down (CheckSupportAndFall), they evaluate the block opposite to the normal. This ensures wall, ceiling, and floor-stuck shards fall immediately when their supporting block is destroyed, preventing "floating shards" bugs.

2. Column-Scan Surface Detection

Instead of a slow $O(N^2)$ brute-force grid scan, the mod uses a $O(scanDepth)$ column-scan algorithm for muzzle blasts. For each X-offset, it scans downward to find the first Air $\rightarrow$ Solid transition. This guarantees finding the actual exposed ground, ceiling, and walls efficiently, allowing the blast radius to safely increase.

💻 Local Developer Setup & Compilation

To build the project under game version 6.1 without committing your absolute system paths or manually copying game DLL files, configure your local environment:

1. Configure your local path

Create a file named LocalDev.user in the project root directory (next to ScavShrapnelMod.csproj). This file is ignored by Git. Paste the following XML and set your game folder path:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <!-- Adjust this path to point to your local Scav v6.1 installation -->
    <GameDir>D:\SteamLibrary\steamapps\common\Casualties Unknown Demo\</GameDir>
  </PropertyGroup>
</Project>

2. How reference resolution works

  • Directory.Build.props imports your LocalDev.user early.
  • It calculates ManagedDir dynamically.
  • ScavShrapnelMod.csproj determines if the Assemblies exist in your game's CasualtiesUnknown_Data/Managed/ directory.
  • If they do, it compiles directly against your local game files. If not, it falls back to the Libraries/ directory.

3. Build & Auto-Launch

Open the project in Visual Studio Code.

  • Press Ctrl + Shift + B (or select the build task) to compile and auto-deploy the DLL into your BepInEx plugins folder.
  • Run the build-and-launch compound task to compile, deploy, and launch the game executable automatically.