Skip to content
This repository was archived by the owner on Sep 29, 2026. It is now read-only.

Latest commit

 

History

History
125 lines (75 loc) · 28.8 KB

File metadata and controls

125 lines (75 loc) · 28.8 KB

People Playground API compatibility

The loadable bridge and authoritative runtime are in src/. Core members were checked against the installed game assemblies; focused native pose/standing IL and the official Shady Code Rejection rules were checked again on 2026-09-12. Source-linked test doubles do not establish in-game physics behavior.

Mod target boundary

The game-facing project targets net48 and references installed People Playground/Unity assemblies. The installed game executable and UnityPlayer.dll report Unity 2020.3.1.7841951; Assembly-CSharp.dll reports CLR image runtime v4.0.30319, and the bundled Mono mscorlib.dll reports 4.6.57.0. This is a Unity Mono/.NET Framework-era runtime, not .NET (Core/5+) in the game process. The installed ppgModCompiler is a separate x86 .NET 10.0.2 process using Roslyn 5.0.0; its CompileMod IL constructs CSharpParseOptions with LanguageVersion.CSharp14 (1400). The compiler references netstandard.dll, Mono mscorlib.dll, System.dll, System.Core.dll, and the installed game/Unity assemblies; this does not prove that every .NET Framework 4.8 API is available. The current code uses members present in the inspected references. The game project and runtime test harness compile the same physical src/Core/LifBrain.cs; no separate offline brain library is loaded by the game.

Public active members

API Use and boundary
PersonBehaviour.DesiredWalkingDirection Bounded walking request, cleared on stop/disable.
LimbBehaviour.InfluenceMotorSpeed(float, float) The game interpolates joint speed toward the request. Stop uses influence 1, independent of IsCapable; no-joint limbs cannot be driven by this API.
GripBehaviour.Use(ActivationPropagation) / DropObject() Optional grab/drop. Installed Use does not read its propagation argument. A zero/invalid active request leaves an existing hold unchanged; stop releases grips explicitly and independently of capability.
CirculationBehaviour.BloodRegenerationPerSecond / LimbBehaviour.RegenerationSpeed Bounded boosts never lower an existing baseline. Cleanup restores only an unchanged last assignment owned by this controller. A newer external write wins.
PersonBehaviour.AdrenalineLevel Bounded stimulation/calming during active control.
PhysicalBehaviour.BurnIntensity Bounded reduction during active control.
ContextMenuOptionComponent.Buttons / ContextMenuButton.Identity Controlled people suppress only the native walking/protective/sitting/resting/stumbling pose actions; unrelated context-menu actions remain available and the original buttons are restored when the controller is disabled.

Restorative outputs are engineered interventions. They do not demonstrate human physiology or a biological fly-to-human chemistry mapping.

Limb discovery and routing

Each read reconciles child limbs (including inactive children) and the public PersonBehaviour.Limbs array. Previously discovered detached limbs remain tracked; destroyed Unity objects are removed. Each surviving limb has one controller and collision probe. Names classify head, core, arm, hand, leg and foot roles. Side names are resolved through the hierarchy: explicit left/right takes priority; front->right and back->left is a documented game-plane convention; unknown naming receives an average channel. Position is not interpreted as anatomical side. Exact prefab mapping still requires the manual checklist.

Missing grips do not disable joint or walking control. Incapable limbs have old motor commands and grips cleared. Terminal, invalid-health, consciousness <= 0.8, unavailable consciousness and freeze states suppress walking, limb/grip requests and active chemistry. Only terminal/invalid reads stop neural stepping; nonterminal unconsciousness is still sampled. Recovery from terminal state begins with cleared neural state.

Sensory mapping

Source Direct members sampled Interpretation
PersonBehaviour Health, pain, shock, consciousness, oxygen, adrenaline, fire, wetness, speed, angle, balance, heartbeat, brain damage/time, brain death, seizure time, floor contact Bounded scalars and flags. Nonfinite average health is invalid data, not invented death. Falling combines downward velocity from tracked limb physical bodies with floor-contact gating.
LimbBehaviour Health/initial health, joint stress, dismemberment, breakage/shattering, temperatures, frozen/paralysed/capable/numb/lung/zombie state Injury/temperature/state aggregations are approximations. LimbLoss is the fraction of tracked limb slots marked dismembered/disintegrated, while LIMBS lost=x/y shows the underlying count.
CirculationBehaviour Bleeding, blood amount, heart rate, flow/disconnection/circulation, wound counts, internal bleeding, LiquidDistribution Blood deficit, wound severity and fluid fractions are bounded approximations.
Liquid Exact case-sensitive GetIdentity; display-name fallback for text only; nullable RefFloat.Raw; TotalLiquidAmount Enumerates all current circulation contents. Finite positive amounts/total required; empty circulation contributes zero and unavailable/invalid data is flagged. Peak fractions are exposure proxies. See the stock mapping below.
PhysicalBehaviour Burn state/progress, temperature, charge, wetness, underwater/lava/stab/contact/held/weightless/sliding/disintegration, native rigidbody and audio source Underwater is separate from wetness. Submerged hypoxia reports simultaneous submersion and oxygen deficit, not proof that water caused the deficit; hypoxia alone is low oxygen. Projectile awareness requires a native projectile component; BulletPenetration alone is not treated as projectile evidence. Falling reads the native limb rigidbody velocity, not unrelated child bodies or horizontal walking speed.
Collision callbacks Relative contact velocity excluding the owner hierarchy and tracked detached limbs CONTACT IMPACT plus a decaying Vibration channel. This is mechanical contact, including self-generated foot-floor impacts, not external sound. A projectile callback is raised only for an external collider carrying a native projectile component.
Unity overlap/closest point/linecast and ambient grid Nearby physical colliders, horizontal surface direction, nearest-visible targets in five head-relative bands, and native local ambient temperature Nearby is bounded proximity. Vision is only a bounded visual proxy: a candidate in the head-facing frontal 180-degree field must be the first external hit in a reusable multi-hit linecast and is attenuated by combined ambient/local-light proxy; owned colliders are ignored so a status anchor inside its own body does not self-occlude, while an external wall still blocks the target. It has no color, recognized identity, retinal depth map or semantic recognition. Valid Collider2D.bounds and finite target/anchor rigidbody velocities supply approximate angular size, expansion and transverse motion for each sampled visible band. The original nearest-target fields remain telemetry; the five-band frame supplies live visual encoders. AmbientTemperatureGridBehaviour.GetTemperatureAtPoint supplies local ambient heat/cold; dynamic nearby PhysicalBehaviour.Temperature values and native LavaBehaviour.LavaTemperature add distance-attenuated object cues, while static map geometry is excluded. The default ambient value of 20 is neutral. This is not native long-range radiation. A fixed 128-collider overlap and at most 16 visibility queries can omit objects in crowded scenes. Filled 32-hit linecasts fail closed; incomplete searches are labeled. Known own limbs are excluded after detachment too.
Light/audio Ambient grayscale plus native light-owner sprite proxies; active unmuted nearby physical-object audio volume and optional AudioSource.GetSpectrumData Light/playback proxies, not visual perception or general hearing. Ambiguous generic Root/Root audio is conservatively ignored; this is not proof of source ownership (see caveat below).

The exact neural mapping is documented in sensory-mapping.md. Contact input is downweighted so ordinary floor contact is weaker than an impact. Blood loss is normalized against a per-circulation positive baseline; unavailable readings remain unknown. Legacy Proprioception combines body-motion proxies; new joint encoders read public LimbBehaviour.Joint / HingeJoint2D.jointAngle, jointSpeed and connectedBody. Angle/speed magnitudes are divided by 180, and load uses valid connected-joint stress. These are global body aggregates, not individually calibrated fly leg receptors.

Audio bearing uses the winning AudioSource transform, and attenuation/diagnostic distance use that same position. Visual bearing uses the nearest line-of-sight collider surface. Audio and the legacy visual diagnostic project delta.x / distance onto world horizontal; the visual encoder now uses signed head-relative bearing/90 instead (positive world-plane CCW maps to R populations). See head-relative vision; missing/nonfinite/coincident geometry has no signed direction. Approach is positive radial closing speed between finite target/anchor native rigidbody velocities, divided by 10 and attenuated by the existing visual signal. This remains a fallback when valid bounds geometry is unavailable. With valid geometry, the encoder uses bounds-derived angular expansion/size and sweep relative to measured head angular velocity in degrees/second, not rendered retinal flow or semantic recognition. Tilt uses finite native AngleOffset/180; anchor velocity XY/10 remains telemetry, not invented wind. Smell, taste, humidity and chemical receptors are not fabricated. A positive connected-limb health drop supplies an explicitly engineered tactile injury-event input; native pain is a separate game reading. Nearby direction never directly selects an escape command.

Display and safety

The installed ModLoader.LoadModAt automatically reads README.txt only when its file length is at most 5000 bytes (not 5120). Larger files are skipped, leaving RichReadme unset; ModEntryBehaviour.ShowDescription then shows the manifest description/author fallback. The earlier 6448-byte README caused that exact fallback. RichReadme does not need to be added to the manifest. Deployment now checks the generated UTF-8 byte count after build-marker replacement, and the compact in-game README preserves source attribution and the full MIT notice. Restart the game after updating files to reload this cached metadata; verify the PLAY/READ THE PANEL sections appear in the mod description.

The primary display uses a Unity screen-space overlay Canvas with TextMeshPro with an opaque background, wrapped scrollable pages, text-size controls, collapse and a person selector. Display construction is passive; registration and pose-menu suppression begin only from the enabled lifecycle, so an initially disabled controller cannot claim the selected panel or alter native menus during Awake. It has no world-space label, lighting material or camera-facing transform. World coordinates identify the selected person; no camera movement is performed. REQUEST is desired motor output; LIMBS reports driveable/submitted joint counts and the submitted walking request, not achieved physical motion. Nonterminal motor eligibility uses local joint, fracture, dismemberment, disintegration, paralysis and circulation-disconnection evidence rather than the game's person-wide IsCapable flag; this prevents submersion from disabling every healthy limb. In a terminal state, the display reports one explicit stopped-control reason instead of labeling every limb independently incapable. NEURAL distinguishes pending-input targets, active neurons, input-integrated and decay-only updates, dropped threshold crossings, fired neurons and the STEADY/OVERLOADED scheduler state. The sensory label and its value share a single selection path.

Mod sources use memory streams, gzip and a pure byte/word SHA-256 implementation on texture bytes. The game rejects using System.Security and its subnamespaces, so the runtime checksum has no platform cryptography dependency; source guards cover forbidden namespace prefixes and aliases. Offline tests compare the portable checksum against known vectors, padding boundaries and the framework SHA-256 implementation. They do not use filesystem APIs, reflection, networking, process execution, native interop, direct rigidbody forces, damage injection or liquid injection. The display creates a nonphysical texture, disposes it with its controller and creates no gameplay objects. No game persistence is implemented.

The solution compiles the mod against installed references. Two source-linked test harnesses check neural and adapter contracts with test doubles; the manual game checklist remains required for native loading, physics, rendering and performance acceptance.

Native movement ownership verified on 2026-09-12

PersonBehaviour.Update decays DesiredWalkingDirection; LateUpdate calls DetermineActivePose, which consumes that request and pose overrides. The controller uses [DefaultExecutionOrder(-1000)], and the inspected PersonBehaviour type has no custom execution-order attribute, so the adapter refreshes its latest permitted nonzero walking intent after native Update decay but before the default-order native LateUpdate; full sensory/chemical/neural application remains on the configured neural tick. LimbBehaviour.ManagedFixedUpdate can call ApplyPoseOverrides, MoveIntoPose, InfluenceMotorSpeed and FakeStandUpright. The latter uses FakeUprightForce * MotorStrength * GetMassStrengthRatio() and the active pose's upright multiplier before native torque application. Direct fly control is enabled by default and also suppresses every discovered pose's ShouldStandUpright, ShouldStumble, UprightForceMultiplier and ForceMultiplier, in addition to the limb balance/stumble fields; all captured values are restored when disabled or the controller is removed. This is best-effort pose-assist suppression: pose selection, joints, gravity, collisions and other native mechanics remain active, so exclusive neural control is not claimed.

Unknown data and diagnostic boundaries

Health, oxygen, consciousness, circulation, derived damage, minimum limb health and blood deficit have explicit validity flags. Nonfinite oxygen never becomes low oxygen/hypoxia; invalid consciousness suspends active output without claiming unconsciousness. Missing circulation does not default to healthy. Nonfinite blood after a baseline does not become total blood loss. Invalid per-limb health is excluded from damage/minimum-health aggregation and disables only that limb's actuator. Limb-loss fractions still count every tracked limb. Unavailable temperatures and brain-damage duration do not create temperature or injury signals.

The acid-pool signal uses native progress/pain only when the status anchor touches its collider (0.05 world-unit tolerance). This is limited contact evidence, not chemical sensing throughout the body. Lava proximity remains a hazard/heat cue rather than proof of bodily lava immersion.

UnityEngine.UIModule, UnityEngine.UI, Unity.TextMeshPro and UnityEngine.TextRenderingModule provide the screen UI. The installed mod compiler includes these assemblies but excludes UnityEngine.IMGUIModule; adding a reference to the project does not change the game compiler reference list. scripts/ai/Test-GameCompilation.ps1 compiles the manifest sources against the exact references recorded in the installed compiler's last_instructions. This catches the reported GUIStyle/GUIContent failure; it also runs the installed compiler's low-risk and high-risk semantic scanners. These checks do not prove rendering, UI input priority or full loader acceptance. Brain-map colors group real superclass metadata. The X/Z image samples finite source soma positions and actual fired IDs; it has no invented positions, human anatomy, semantic retina, or biological firing-rate claims.

The official Shady Code Rejection rules are checked offline by scripts/ai/Test-ModSourceSafety.ps1, using the Roslyn parser bundled with PowerShell 7. This checks every manifest source, forbidden identifier tokens (including escaped forms), extern, forbidden using prefixes and aliases. Tools/tests may use filesystem/reflection APIs offline; they are not shipped in mod.json. Final native loading must still be tested with rejection enabled. The setting is never modified by the mod or the test.

Verified motor and adrenaline boundaries

Installed native IL shows DetermineActivePose requires abs(DesiredWalkingDirection) >= 0.5; Update reduces its magnitude by 1 unit/second and clamps it to -4..4. This adapter conservatively caps submitted walking at -1..1, defaults WalkingRequestGain to 2, floors any nonzero usable final request at 0.55 after hazard scaling, and refreshes the latest permitted walking request every rendered frame after native decay. Zero neural intent and a disabled gain remain zero; stopping, suspension and loss of the latest movement permission clear the cached intent. A -0.46 neural request therefore submits at least -0.55 rather than remaining below the native pose gate.

InfluenceMotorSpeed interpolates the requested speed into JointMotor2D.motorSpeed. Unity's Hinge Joint 2D manual specifies degrees per second. The adapter defaults full-scale normalized joint requests to 30 deg/s, with a configurable 0..120 bound. This replaces the accidental +/-1 deg/s target. These are engineering defaults, not measured stock-gait calibration; native torque, strength, pose selection and constraints remain in control. Nonfinite settings stop affected joint requests immediately. The game can randomize native motor application when PersonBehaviour.BrainDamaged is true, even though the mod's decoder is deterministic.

Native Update also decays AdrenalineLevel by 1 unit/second and clamps it to 0..20. Inspected Damage/BreakBone/AddPain methods do not establish an injury-to-adrenaline rise; other game paths may still modify it. The display now distinguishes raw adrenaline from its normalized 0..1 reading. Pain/shock no longer generate a chemical calming request, and sensed adrenaline no longer generates a stimulation feedback request. Existing explicit liquid sedation/stimulation mappings remain engineered adjustments; nonzero adjustments preserve the native 0..20 range instead of clamping raw adrenaline to the 0..1 normalized range. Native pain is not painted onto unrelated sensory populations. A newly observed connected-limb health drop now supplies a one-sample tactile injury proxy; no adrenaline surge or subjective pain is inferred. Measured mechanical/thermal consequences also drive their corresponding encoders. Native person health and computed tracked-limb damage are separate quantities; the native average-health getter alone does not establish its aggregation policy.

Audio history retains only the last source description and a real-time timestamp. Sound remains a fresh frame value and returns to zero when playback stops or is filtered; the UI labels current-sample detection separately from last-heard history.

Liquid and syringe coverage

Static IL inspection of the installed 1.27.17 Assembly-CSharp.dll, Global.Awake, found these 41 literal Liquid.Register IDs. Liquid constructs its registry with the default case-sensitive string comparer. This inventory was read without running game bootstrap or injecting liquids. The table documents adapter exposure categories, not measured effect severity or a biological receptor map.

Exposure route Exact stock IDs
Normal blood; no general exposure drive BLOOD
Hazard exposure GORSE BLOOD, OIL, NITRO, TRITIUM, COOLANT, REANIMATION AGENT, ACID, BONE EATING POISON, INSTANT DEATH POISON, FREEZE POISON, OSTEOMORPHOSIS AGENT, VESTIBULAR POISON, MUSCLE POISON, NUMBING POISON, EXPLOSION POISON, CRUSHING POISON, DISTORTION POISON, CIRCULATION POISON, COMBUSTION AGENT, TISSUE DECONSTRUCTION AGENT
Sedative exposure KNOCKOUT POISON
Stimulant exposure ADRENALINE
Restorative exposure COAGULATION SERUM, LIFE SERUM, MENDING SERUM, IMMORTALITY SERUM, REGENERATION SERUM
General exposure only EXOTIC LIQUID, INERT LIQUID, BEVERAGE M04, WATER BREATHING SERUM, PAIN KILLER, INERT PINK LIQUID, MIRRORISING AGENT, TRANSPARENCY AGENT, MASS AGENT, DEBUG LIQUID 001, ULTRA STRENGTH SERUM, DURABILITY SERUM, ENHANCING SERUM

Other registered IDs and unregistered display names get general exposure only, even if their text contains “acid”, “blood”, “healing” or “water”. Stock IDs replaced by another mod retain these stock assumptions; there is no inspection of custom effect implementations. Future game versions require rechecking the table. General exposure only does not mean harmless: native effects are still observed through the existing state sensors. Exposure categories remain telemetry and existing engineered control constraints/adjustments. Internal concentrations do not stimulate taste, smell or unrelated visual neurons, and there is no learned understanding of each poison.

The Senses list reports the largest fraction for each identity in any tracked limb (including known detached limbs), not a weighted whole-body concentration. Category channels likewise use the largest individual liquid fraction, not summed mixture toxicity. Entries disappear when absent from the next sample; unavailable readings are labeled incomplete. Effects can persist after the liquid is metabolized: native IsZombie is separately reported as zombie(native) as telemetry; it is never inferred from REANIMATION AGENT alone. Pain, consciousness, oxygen, health, numbness, paralysis, temperature and other supported native states remain separate inputs. A nearby syringe or a liquid's appearance does not grant remote chemical sensing.

Native effect-method inspection explains important exceptions: WaterBreathingSerum.OnUpdate writes OxygenLevel; no plain WATER ID is registered, so it must not produce internal-water exposure. DurabilitySerum modifies Health/InitialHealth, UltraStrengthSerum modifies health/strength/regeneration-related fields, and MuscleEnhancementSerum modifies BaseStrength/RegenerationSpeed; those exposures no longer request adrenaline. PainKillerLiquid changes pain/motor state and can cause damage; ExoticLiquid changes pain/temperature; BeverageM04 changes adrenaline. These unusual liquids remain general exposure rather than pretending their concentration measures a single effect. Native fields reflect their actual consequences where the adapter supports them. No new damage, liquid injection or syringe effect is enacted by sensing. The pre-existing bounded restorative/chemistry decoder remains an engineered gameplay feature, not a model of drug action.

Audio ownership caveat: the adapter excludes tracked self sources by object/person identity. It also conservatively filters ambiguous Root/Root sources with no identifiable PersonBehaviour, including numbered and (Clone) suffixes such as Root (3). This name filter cannot prove that an object belongs to the controlled person and may suppress a genuinely external object with those generic names. Identifiable other-person sources remain eligible. A displayed source name alone is not evidence of ownership.

Additional Minecraft adaptation API boundary

Installed native assemblies confirm AudioSource.GetSpectrumData(float[], int, FFTWindow), AudioSettings.outputSampleRate, Collider2D.bounds and Rigidbody2D.angularVelocity. The audio reader uses a reusable 512-bin channel-0 buffer, ignores DC, and splits squared amplitude energy below/above 100 Hz using the captured output sample rate. It calls only the strongest accepted source once per control sample. Nonfinite/negative/empty data, invalid sample rate or UnityException marks the bands unavailable; broad current playback remains readable. Unity builds spectrum history on first use and may initially return empty output. Bin resolution is sampleRate/1024 (about 47 Hz at 48 kHz); these are coarse source bands, not song recognition or ear pressure. See Unity GetSpectrumData.

Damage events compare normalized connected-limb health only while the person is readable/nonterminal. InitialHealth changes, disconnection, invalid samples, suspension and terminal state invalidate history. A limb dying between two valid samples can emit once; already lost limbs do not keep producing injuries. Contact regions use native floor/contact/held flags and recognized limb roles; water alone does not create contact. Bounds geometry requires positive finite radius/distance and finite relative velocities. It approximates rigid 2D collider motion, omitting target deformation/rotation and retinal projection. Native anchor angular speed supplies a separate light-gated VS proxy. Exact inputs, decoder thresholds and unsupported Minecraft features are recorded in sensory-mapping.md and minecraft-adaptation.md.

Accuracy sweep on 2026-09-14

Normalized connected-limb health divides by the actual finite positive InitialHealth, including values below one; over-baseline health clamps before division to avoid overflow. Negative blood amounts are invalid/unknown rather than total loss. A missing CirculationBehaviour now blocks only that limb's actuator with unknown-circulation, matching the sensor's unknown state.

Offline inspection of the installed LimbBehaviour.ActOnImpact found native Vitality used in max(1, Vitality), impact thresholds and internal-bleeding scaling. It is an injury-susceptibility parameter, not a measured remaining-health fraction. The old telemetry mixed this parameter with a health fallback. The existing internal Vitality/VitalityValid fields now carry only derived minimum normalized connected-limb health, displayed as min-limb-health; the native parameter is not reinterpreted as health. This diagnostic does not stimulate a new neural pathway.

Scheduler follow-up: no new game API is required. Integration/decay and bounded spike propagation now run as separate synchronous phases. Counter meanings and measured costs are documented in scheduler-performance.md; dropped-spikes counts rejected threshold crossings, not the old unintegrated active-neuron work.

Local lamp light

The installed assembly exposes LightSprite.SpriteRenderer/Brightness, GlowtubeBehaviour.LightSprite, BulbBehaviour.LightSprite, LEDBulbBehaviour.LightSprite, ActivationToggleBehaviour.LightObject, SingleFloodlightBehaviour.ToToggle and FlashlightAttachmentBehaviour.Lights. The adapter reads these public references plus renderer state/color, sprite.bounds, flip flags, drawMode/size and Transform.InverseTransformPoint/lossyScale. It does not infer lights from arbitrary glowing materials or object names. The game exposes no CPU per-world-point illumination query; local-light-sensing.md specifies the approximation, bounds and unsupported effects. No GPU readback, material writes, reflection or new game manipulation was added.

Pumpkin identity and blood-specific API (2026-09-14)

SerialiseInstructions.OriginalSpawnableAsset, ModAPI.FindSpawnable(string) and Collider2D.IsTouching(Collider2D) are used for explicit stock-Pumpkin gameplay cues, not semantic vision or measured external chemistry. Source matching excludes self/disintegrated/inactive/trigger objects; head contact requires the native collider pair. No name-substring food detection or liquid injection is used.

Installed CirculationBehaviour.GetAmountOfBlood() reads Limb.GetOriginalBloodType() via BloodContainer.GetAmount(Liquid); it does not read all circulating liquids. Native BloodAmount aliases TotalLiquidAmount and is deliberately not used for this measurement. ActualBloodLimit has no managed references in the inspected assembly and is not assumed to be a verified initial capacity. The display exposes raw game units and relative observed-peak deficit separately. Detached limbs are excluded from connected blood measurements, while their liquid identity diagnostics remain separate. Missing/malformed distribution data is guarded before calling the native amount reader. See blood tests and limits.

Object-audio follow-up: the bounded nearby scan includes the native jukebox music source and attached AudioSources, beyond MainAudioSource. Up to 64 unique sources are evaluated; partial scans are labeled. Playback/mute/ownership filters and strongest-source spectrum/direction remain. This is a playback proxy, not sound pressure or music understanding. See checks.