Compare commits

...

207 Commits

Author SHA1 Message Date
ivan tkachenko 1c9645e72d WIP: Add frontend web app player & editor in Vue 3 + Vite
TODO:
- implement viewing & editing.
- Add links to deployment, and CHANGELOG.

style.css

package.json

vite config

.vscode

eslint use --cache

.vscode

add vite-css-modules

editorconfig

tsconfig and updated vue-tsc (fixes most of the type checking bugs)

fix last type errors

audiowaveform

gitignore ESLint

ESLint: ignore autogenerated JSON

lint:fix tsconfig and vite config

migrate icon generating script to TS

eslint src/lib/

eslint stores

eslint src/*.ts

eslint audio

pnpm update

update icon

eslint ahh

import new tracks json

instructions on jq codenames

codenames.json

fix styles broken by import order

eslint audio

app

error screen

footer

copyright year

global header

loading screen

transition

search field

preview

track info

inspector

control

controls

controls range

controls impl

controls index

eslint no-console off

AudioTrack view inspector

cards and sliders

more controls

master volume slider

playhead

library page

player page

timeline markers

timeline markers

header tick

timestamp

timeline clip index

clip empty

clip lyrics

clip palette

clip fadeout

clip default

import order

timeline

timeline panel

timeline track header

timeline trackview

clip view

clip audio

audio waveform

scrollsync

easy lints

eslint store

eslint no mutating props off

pnpm catalog off

add unhead dep

use head

eslint inspector

eslint easy minor stuff

eslint audiowaveform

easy fix

eslint use :key with v-for

fix audio waveforms

inspector makes more sense

season

remove debug

inspector

Merge codenames into main json

bump pnpm

pnpm in particular

enabled

monospace Game Over

Move JSON to assets to avoid caching issues
2026-01-23 15:56:34 +02:00
ivan tkachenko 8942b2ee37 Implement a better way to disable tracks while keeping them in JSON 2026-01-23 15:32:33 +02:00
ivan tkachenko f20a500992 Show Artist & Song metadata in config 2026-01-23 14:34:37 +02:00
ivan tkachenko 6a71ed578b Include Artist & Song metadata in the track info 2026-01-23 14:19:34 +02:00
ivan tkachenko 3490b1c2f3 Bump version 2026-01-23 14:01:00 +02:00
ivan tkachenko cbf1c14e01 Release v1337.9001.68 2026-01-23 05:29:16 +02:00
ivan tkachenko 5258b806d4 Add a new track Arcane 2026-01-23 05:23:53 +02:00
ivan tkachenko 4cc187b525 Split audio tracks metadata into a separate file 2026-01-23 01:52:23 +02:00
ivan tkachenko ecee2a25e2 Reorder [General] config section alphabetically
As a side-effect, this conveniently places the most important option
OverrideSpawnRates at the top.
2026-01-23 00:13:02 +02:00
ivan tkachenko af38056d11 Merge Config.DisplayLyrics and ReduceVFXIntensity
Both are responsible for some sort of VFX. Make the number of options
less overwhelming by merging the two into one.
2026-01-23 00:08:17 +02:00
ivan tkachenko 567597e353 Remove Config.ExtrapolateTime even from Debug build
Just always do it, there is no reason not to.

And maybe try dspTime to replace the whole extrapolation technique.
2026-01-22 23:47:00 +02:00
ivan tkachenko ee2b1574d0 Hide AudioOffset from Lethal Config
It is a niche option, and having two sliders next to each other might be
overwhelming for players.
2026-01-22 23:43:02 +02:00
ivan tkachenko 02903ba537 Adapt to WaterGun-V70PoweredLights_Fix-1.1.0
Don't replace the rest of the patches, because animators and audio would
be broken for reasons yet unknown.
2026-01-22 23:38:57 +02:00
ivan tkachenko b0d5922c3c Replace hotfix in code with a properly rebuilt asset bundle 2026-01-22 23:38:56 +02:00
ivan tkachenko 4e9ba0928f Disable track Yalgaar in release builds
Still will be available in a web player.
2026-01-22 23:38:56 +02:00
ivan tkachenko 6a5cc637ac Rewrite client-side vanilla-compat mode
Amends b8ef4d7937

Networking and playback are fixed, but client-side vanilla-compat mode
can never work as intended, because timers are actually client-side and
not synchronized at all. No matter what your local timer is set to, the
host gets to decide when to pop Jester at a completely random for your
client moment. There can be no meaningful prediction whatsoever.
2026-01-22 23:38:56 +02:00
ivan tkachenko a2cf66476c Deduplicate logs to avoid spamming console with errors each frame 2026-01-20 01:48:39 +02:00
ivan tkachenko a254188f0c Stop farAudio (popGoesTheWeaselTheme) in the only place where it matters 2026-01-17 19:40:42 +02:00
ivan tkachenko 3041d9f73c Merge EnemyAI.OnDestroy patch with cleanups into existing Behaviour
That Harmony patch predated MuzikaGromcheJesterNetworkBehaviour, but
there is no need to have as a separate class, especially not with the
subclass check hack.
2026-01-16 19:38:43 +02:00
ivan tkachenko 908ddeb862 editorconfig: do not suggest null propagation for Unity code 2026-01-16 18:04:07 +02:00
ivan tkachenko 3835e84450 Bump version 2026-01-16 18:04:06 +02:00
ivan tkachenko 835d69d2d0 Release v1337.9001.67 2026-01-13 22:50:25 +02:00
ivan tkachenko 4442daae53 README: Add link to the web player 2026-01-13 22:50:20 +02:00
ivan tkachenko cfff2b808a Tweak disco balls at the factory's start room
Remove all but one in the center and hang it lower.
I don't access to source assets of the bundle, and I have no idea if
reassembling it after the AssetReapper is gonna work.
2026-01-13 22:38:06 +02:00
ivan tkachenko b8accefff7 Ignore code lint IDE0305
Replacing expr.ToArray() with [..expr] doesn't simplify anything.
2026-01-13 21:43:53 +02:00
ivan tkachenko b8ef4d7937 Implement client-side playback with Vanilla Compat Mode 2026-01-13 21:43:52 +02:00
ivan tkachenko dcae12ab36 Add a "NEW" badge to the icon
People get confused why there are two variants of seemingly the same mod.

Use Magic Wand with Threshold 2, Spread 12%, Grow -8px and Feather 1px
to mask white background of the stamp; then duplicate background on top,
set blending to Screen and use the stamp itself as a mask for overlay.
2026-01-13 05:18:58 +02:00
ivan tkachenko ffa2e952c9 Add new track TwoFastTuFurious 2026-01-13 04:57:49 +02:00
ivan tkachenko e05c3b2471 Bump version 2026-01-13 03:18:55 +02:00
ivan tkachenko d59c5a20c1 Add Thunderstore config for automated uploading 2026-01-12 04:00:33 +02:00
ivan tkachenko b1d449cf02 Release v1337.9001.4 2026-01-12 03:22:14 +02:00
ivan tkachenko 3f06cc9aa6 Add new track PickUpSticks 2026-01-12 03:20:03 +02:00
ivan tkachenko a5659fcb09 README: Include a link to an upcoming HookahPlace mod 2026-01-11 16:15:18 +02:00
ivan tkachenko 6271a377bd README: Describe recently added tracks 2026-01-11 16:15:18 +02:00
ivan tkachenko a4cee92d00 Load audio clips on demand, implement cache
Reduces cold-boot memory usage by 400 MB for the current playlist of
58 audio files (27.8 MB).
2026-01-11 16:06:45 +02:00
ivan tkachenko f83f2a72ba Mark AudioClip as nullable 2026-01-11 03:17:49 +02:00
ivan tkachenko afb3e34e71 Implement seasonal content framework
to ensure that New Year's songs won't play in summer.
2026-01-11 02:53:53 +02:00
ivan tkachenko ebd7811b12 Avoid null dereference while reading seed in orbit 2026-01-11 02:13:19 +02:00
ivan tkachenko a64d671527 Add Config.ReduceVFXIntensity option 2026-01-11 00:12:21 +02:00
ivan tkachenko 7eaa5fce75 Add new track DiscoKapot 2026-01-10 23:47:39 +02:00
ivan tkachenko da86ca6a2d Add new track Paarden 2026-01-10 22:51:56 +02:00
ivan tkachenko c4c1919df6 Adjust lyrics for PWNED 2026-01-10 21:10:08 +02:00
ivan tkachenko 869d982b1e Remaster recently added track IkWilJe, rework visual effects 2026-01-10 21:07:15 +02:00
ivan tkachenko 10839ba22c fixup CHANGELOG 2026-01-10 19:45:28 +02:00
ivan tkachenko 398de3dc04 Bump version 2026-01-10 19:41:07 +02:00
ivan tkachenko 4f432968ef Release v1337.9001.3 2025-12-30 23:40:33 +02:00
ivan tkachenko 56cea50a65 add new track IkWilJe 2025-12-30 23:39:01 +02:00
ivan tkachenko 0d416c6f5a Release v1337.9001.2 2025-12-30 22:51:39 +02:00
ivan tkachenko c1d91839e4 add new track HighLow 2025-12-30 22:25:50 +02:00
ivan tkachenko 76189c6ad2 Update BepInEx.PluginInfoProps to version 2.x
2.x implements better namespacing.
2025-12-30 22:25:49 +02:00
ivan tkachenko b6f576d50d Include debug symbols, but strip sensitive source paths 2025-12-20 20:35:15 +02:00
ivan tkachenko a4ca1c86ec Save Harmony own instance in private static
That's how other mods do it. Might be useful to reload patches.
2025-12-19 23:40:46 +02:00
ivan tkachenko 38c9472cb1 Port logging to BepInEx ManualLogSource
- pros: free namespace by default
- cons: Debug level has to be enabled manually in BepInEx.cfg,
  specifically in the section named [Logging.Console]
2025-12-19 23:39:28 +02:00
ivan tkachenko 8a24448cb6 Consistent ordering of Easing functions in C# 2025-12-06 23:26:08 +02:00
ivan tkachenko a74bbfaee2 Add JSON exporter to debug builds 2025-11-23 15:56:58 +02:00
ivan tkachenko ad0a20cc7e Fix consistency of capitalization in csproj 2025-11-11 15:45:42 +02:00
ivan tkachenko 51e578f2da Migrate .sln to modern and simple .slnx 2025-11-10 18:10:21 +02:00
ivan tkachenko 3563fa2b36 Bump version 2025-11-10 18:08:16 +02:00
ivan tkachenko f790decc4d Release v1337.9001.1 2025-11-01 23:37:35 +02:00
ivan tkachenko 5a8f0201a3 Tweak color visual effects and lyrics for MoyaZhittya and other tracks 2025-11-01 23:37:34 +02:00
ivan tkachenko 825355dd54 Raise the default audio volume, add a configuration slider 2025-11-01 23:37:34 +02:00
ivan tkachenko c62535841a Shuffle README content, add link to mod's Discord thread 2025-11-01 18:20:41 +02:00
ivan tkachenko b0d96ff67e Bump version 2025-11-01 18:20:41 +02:00
ivan tkachenko 3607ccc92f Release v1337.9001.0 2025-10-15 19:10:29 +03:00
ivan tkachenko 8570505758 Rewrite README, add self-hosted videos 2025-10-15 19:10:06 +03:00
ivan tkachenko 049a14e440 Use requiresRestart: false directly, remove Default() options factory
Now, without an additional CanModifyCallback setup, Default is just a
pointless overhead.
2025-10-15 15:55:29 +03:00
ivan tkachenko 1ec8275831 Drop restrictions on when/whether host/clients can modify config
Lethal Config does not refresh that state reliably, it has only caused
bugs and annoyances so far. If someone wants to change the track mid-day,
there is a small chance to desync though.
2025-10-15 15:49:53 +03:00
ivan tkachenko 9efe6adaf3 Add a new track ReelGoon 2025-10-14 19:00:11 +03:00
ivan tkachenko a5b117e26d Add a new track Whistle 2025-10-14 17:48:37 +03:00
ivan tkachenko 01332ab77f Add a new track BbIXODaHET 2025-10-14 17:48:37 +03:00
ivan tkachenko 7aa3570b33 Fix internal representation of track AttentionPls
Members of track group were never intended to be Selectable.
2025-10-14 17:48:36 +03:00
ivan tkachenko e7866fda55 Fix division erroneously rounding to integers
This fixes LoopOffset which is a non-integer factor or Beats.
2025-10-14 17:48:36 +03:00
ivan tkachenko cd9e0a7a10 Compensate for loudness level -14 LUFS of audio files 2025-10-14 17:48:36 +03:00
ivan tkachenko 8223425b19 Remaster all tracks to target consistent loudness level of -14 LUFS
Add multiple intros for BeefLiver.
2025-10-14 16:53:11 +03:00
ivan tkachenko 9bf3a80341 Bump netcode-patch to support v73 2025-10-11 21:59:48 +03:00
ivan tkachenko 72a8016ab5 Clean up whitespace 2025-10-08 02:30:46 +03:00
ivan tkachenko 9619a75427 Bump version 2025-10-08 02:30:32 +03:00
ivan tkachenko ceaac4e01b Release v1337.420.9004 2025-09-27 03:13:49 +03:00
ivan tkachenko aea755361b Added new track AttentionPls, implement HUD effects as a time series / timeline 2025-09-26 18:07:11 +03:00
ivan tkachenko e67c72951e Override DeathScreen / GameOver text, add support for per-track strings
Custom message is shown only if the player dies to a Jester.
2025-09-22 03:01:41 +03:00
ivan tkachenko 0fadf50bf4 Bump version 2025-09-22 03:00:16 +03:00
ivan tkachenko 585ef604ff Release v1337.420.9003 2025-08-25 12:15:20 +03:00
ivan tkachenko 99babe8bdf Substitute placeholder nulls with per-light initial color for transitions
Fade out and first color transitions used to assume white as a default
color, which is not always the case e.g. in Mineshaft tunnel tiles. Use
nullable from/to/color fields, and substitute them with per-light
initial color data in a new virtual method that calculates colors.
2025-08-25 01:29:39 +03:00
ivan tkachenko bbd9b0204f Rename PoweredLightsAnimators.cs to PoweredLights.cs
For simplicity, but also because it already handles more than animators.
2025-08-24 22:34:33 +03:00
ivan tkachenko 70eabe75dd Bump version 2025-08-24 22:29:47 +03:00
ivan tkachenko 63de62111f Release v1337.420.9002 2025-08-23 02:34:17 +03:00
ivan tkachenko 4cc9713fa7 Fix resetting to wrong initial colors, e.g. in Mineshaft tunnel tiles
This does not fix fading out and transitioning to the very first palette
color though, but fixing that would require color events to
be "personalized" per-light, which is currently not supported.
2025-08-23 01:49:12 +03:00
ivan tkachenko 8710df7525 Change config value for Override Spawn Rates to true by default 2025-08-22 16:09:01 +03:00
ivan tkachenko 9d23fd5b95 Downgrade LobbyCompatibility to optional dependency
Since it does not prevent unmodded clients from joining, there is no
reason for literally any mod to require it.
2025-08-22 16:05:42 +03:00
ivan tkachenko 4516b853cd Remove remaining CSync code and references
There were issues with clients not being able to join, potentially
caused by linked (even though actually unused) CSync library.
2025-08-22 15:16:24 +03:00
ivan tkachenko b3767cbbf0 Add "polyfill" for IsExternalInit C# feature
Imperium does this as well, and the whole internet would tell you to do
this too, so it should be fine.
2025-08-22 15:16:24 +03:00
ivan tkachenko 327e606deb Drop required properties syntax
Sometimes, seemingly after random unrelated changes, it might stop
compiling with internal compiler error messages about missing features
and attributes. .NET Standard 2.1 is not supposed to support any
features beyond C# 8.0, while `required` attribute was introduced only
in C# 11 or 12, it's hard to tell.
2025-08-22 15:16:24 +03:00
ivan tkachenko 70e45d5ba2 Remove unused class 2025-08-22 15:16:24 +03:00
ivan tkachenko d4d3e15de3 Clean separation between track data and config overrides
In debug builds Config keeps a reference to the last set original track
instance from which it can load original values.
2025-08-22 15:16:23 +03:00
ivan tkachenko 525c0e108f Refactor CurrentTrack to be less dependent on a global static 2025-08-22 15:16:23 +03:00
ivan tkachenko 73ad702684 Rewrite AudioSource handling from scratch 2025-08-22 15:16:23 +03:00
ivan tkachenko e67de4556c Move BeatTimeState from global static to per-Jester-instance Behaviour 2025-08-22 15:16:11 +03:00
ivan tkachenko 0b0383003f Reset BeatTimeState for good measure
Hopefully will fix Mineshaft lights somehow getting stuck in multiplayer.
2025-08-22 15:16:11 +03:00
ivan tkachenko 9ed98197f8 Remaster track Beha and BeefLiver at conventional 44100 Hz 2025-08-22 15:16:09 +03:00
ivan tkachenko fe5752cbff Remaster track Beha and BeefLiver at conventional 44100 Hz 2025-08-21 15:30:47 +03:00
ivan tkachenko c6b128270f Add new track OnePartiyaUdar 2025-08-15 00:52:38 +03:00
ivan tkachenko 852d866073 Bump version 2025-08-15 00:51:53 +03:00
ivan tkachenko 6a9ea8d4af Release v1337.420.9001 2025-08-14 19:17:35 +03:00
ivan tkachenko 42c6179ba5 Add new track Beha with three variants of intro 2025-08-14 19:13:20 +03:00
ivan tkachenko 5649a18633 Split Track into Selectable and Audio interfaces, add support for groups 2025-08-14 18:48:54 +03:00
ivan tkachenko 47f984cd28 Allow tracks to share common audio clip files
Send one request per file name. File names can be explicitly overridden.
2025-08-14 15:38:59 +03:00
ivan tkachenko fc3a62e511 Rename Start segment to Intro to reduce some confusion
Confusingly, "start" may refer to too many things in different places,
while "intro" would unambiguously refer to an audio clip that plays
first before the loop starts.
2025-08-14 15:11:46 +03:00
ivan tkachenko 5f0c890682 Remove unused method 2025-08-14 15:09:31 +03:00
ivan tkachenko 59a069f51b Bump version 2025-08-14 15:09:27 +03:00
ivan tkachenko df796965f2 Release v1337.420.69 2025-08-11 22:28:57 +03:00
ivan tkachenko 26f9d2cf9f Print tracks length in debug builds, and remove unnecessary non-null assertion 2025-08-11 22:28:32 +03:00
ivan tkachenko a950093f8e Sort tracks by name, so they are easier to find in the config 2025-08-11 22:28:32 +03:00
ivan tkachenko 8842005898 Add new track BeefLiver 2025-08-11 22:28:31 +03:00
ivan tkachenko b4ae4bad41 Config: More usable range for fading out 2025-08-11 22:28:31 +03:00
ivan tkachenko 69e64397a0 Extrapolate AudioSource playback time to get smoother transitions
AudioSource only updates about 25 times per second, meaning that even at
30 fps some adjacent frames would be calculated as having exact same
timestamps and render duplicated colors. At 100+ fps more than 2/3 of
the frames would be duplicates.

As a drive-by change, split complex logic of BeatTimeState into smaller
classes. Most of the time the state needs to maintain some boolean flag
which it flips once and stays that way, like HasStarted, IsLooping.
2025-08-11 22:28:31 +03:00
ivan tkachenko 3d0795f04d Drop CSync as a dependency from Release builds
Since the rewrite of track selection to a custom netcode, CSync is only
needed for debug/development builds now.
2025-08-11 22:28:31 +03:00
ivan tkachenko 4abd0fb612 Fix stale event handlers causing errors in console 2025-08-11 22:28:30 +03:00
ivan tkachenko dd3c9647e3 Bump version 2025-08-11 22:28:29 +03:00
ivan tkachenko 8b2f4428bb Release v1337.69.420 2025-08-07 20:27:58 +03:00
ivan tkachenko 0dca416958 Rewrite track choosing event to custom netcode 2025-08-07 20:27:57 +03:00
ivan tkachenko 1aa8c1ddfa Fix Disco Ball hanging around after being disabled 2025-08-07 20:27:57 +03:00
ivan tkachenko 75d0ee2c1d Bump version 2025-08-07 20:27:57 +03:00
ivan tkachenko 2e938dfc8d Release v13.37.9001 2025-08-05 05:10:48 +03:00
ivan tkachenko 1ffdd5d97e Add spawn rate patch to make the event more likely 2025-08-05 05:10:21 +03:00
ivan tkachenko 276fbbec22 Clean up mention of removed config option "Enable Color Animations"
Amends 2a28a36a69
2025-08-05 05:10:11 +03:00
ivan tkachenko 05749ff122 Add Animator and Audio to MineshaftStartTile 2025-08-03 00:31:07 +03:00
ivan tkachenko f131ad7148 Fix NarrowHallwayTile2x2 mineshaft lights flickering 2025-08-03 00:31:07 +03:00
ivan tkachenko f50989b5ae Refactor: Optimize DiscoBallManager to create and cache at start of round 2025-08-03 00:31:06 +03:00
ivan tkachenko 72adb9e713 Refactor: Fix up visibility and static modifiers, and other minor things 2025-08-02 16:25:45 +03:00
ivan tkachenko 76e9ca3595 Refactor: Make State an internal class of JesterPatch class 2025-08-02 16:12:44 +03:00
ivan tkachenko b6f2ca355b Refactor: Factor out displaying lyrics as a tip in its own method 2025-08-02 15:54:07 +03:00
ivan tkachenko 78370da460 Fix LEDHangingLight (GarageTile & PoolTile) lights flickering 2025-08-02 15:50:59 +03:00
ivan tkachenko 4d84a2d001 Fix multiple Light components per animator
Add them all to the allPoweredLights list,
not just the whatever first one was found.
2025-08-02 15:50:59 +03:00
ivan tkachenko 0eb02698eb Fix KitchenTile lights flickering 2025-08-02 01:04:12 +03:00
ivan tkachenko c7b67b9042 Update manifest, README and project files 2025-08-02 01:04:11 +03:00
ivan tkachenko f53f837e3f Bundle CHANGELOG.md 2025-08-01 23:10:36 +03:00
ivan tkachenko 86644388f3 Bump version 2025-08-01 23:10:35 +03:00
ivan tkachenko c0e7185321 Release v13.37.1337 2025-08-01 16:49:42 +03:00
ivan tkachenko 9062f386de Fix/add light flickering with animator controllers 2025-08-01 16:48:16 +03:00
ivan tkachenko 3a2eaad493 Add more light flickering to the track Kach 2025-08-01 02:55:27 +03:00
ivan tkachenko b70e868ac4 Rename DiscoBall asset bundle
There is going to be another bundle, so we want some distinctive names.
2025-07-31 21:44:52 +03:00
ivan tkachenko bacb9f07c7 Use StartOfRound.Instance.audioListener for lyrics events
Probably doesn't make a difference, but it's nice to be able to
calculate audio source<->listener distance directly.
2025-07-30 20:09:17 +03:00
ivan tkachenko 2a28a36a69 Config: Remove EnableColorAnimations toggle
Turns out, it doesn't really affect anything. AMD on Linux would lag anyway.
2025-07-30 18:56:34 +03:00
ivan tkachenko 841ccc74ed Fix color transition from a negative beat 2025-07-30 18:56:33 +03:00
ivan tkachenko 8729515537 Fix timings of fade out and lyrics for DeployDestroy 2025-07-30 18:56:33 +03:00
ivan tkachenko 991e2a56b7 Fix color right before wrapping
The buggy Split method was erroneously creating a looping span despite
explicitly passing `isLooping: false` parameter because with
`beatToInclusive: LoopBeats` wrapping will occur regardless. This
messed up with Duration calculations, and eventually caused the last
beat default to transition with t=0, when it should really be static.
2025-07-30 18:56:33 +03:00
ivan tkachenko c689198588 Fix fading out: set pure black at the end 2025-07-30 18:56:33 +03:00
ivan tkachenko 667368d719 Add specialized color transition event to improve debug output 2025-07-30 18:37:59 +03:00
ivan tkachenko 6a0be0d780 Enable nullable reference types 2025-07-30 18:37:58 +03:00
ivan tkachenko 0573091162 Auto formatting 2025-07-30 18:37:58 +03:00
ivan tkachenko 2ef0fc3bd9 Fix up all logs to use nameof() instead of hardcoded string 2025-07-30 18:37:58 +03:00
ivan tkachenko ce437aa86c Events: Mark BaseEvent as abstract
It's not useful on its own
2025-07-30 18:37:57 +03:00
ivan tkachenko 7ed299ead8 Fix AudioSource distance check for lyrics event
It was checking maxDistance of a non-overridden loop clip during windup.
2025-07-30 18:37:56 +03:00
ivan tkachenko f959a4ebb2 Setup LobbyCompatibility as a dependency
This should help to avoid desync issues.
2025-07-30 01:29:07 +03:00
ivan tkachenko 7a5013524d Prevent Publicizer Warnings from Showing 2025-07-30 00:08:08 +03:00
ivan tkachenko 14a57fcae7 Mark referenced packages with Private attributes
Apparently, this is considered a good practice. Although Private="false"
is supposed to not copy the dependency into the output directory, which
didn't happen anyway?
2025-07-30 00:08:08 +03:00
ivan tkachenko 47876b18bf Fix up csproj XML formatting 2025-07-29 23:45:20 +03:00
ivan tkachenko 5abad0b1ba Bump version 2025-07-29 23:45:19 +03:00
ivan tkachenko 1cdbdf2f09 Release v13.37.911 2025-07-21 19:16:25 +03:00
ivan tkachenko 45a73793fb Add support for pre-v70 Mansion Main tile. 2025-07-21 19:07:36 +03:00
ivan tkachenko 581d9701bd Remove redundant call to private method FlickerPoweredLights
FlickerPoweredLights is a private coroutine.

FlickerLights is the public method that internally starts and stores the
FlickerPoweredLights coroutine.
2025-07-21 19:07:36 +03:00
ivan tkachenko 49ac86e6f9 Add compatibility section to the README
readme
2025-07-21 19:07:35 +03:00
ivan tkachenko 0f8ab1a75b Add Changelog 2025-07-21 19:07:35 +03:00
ivan tkachenko dda00ce228 Bump version 2025-07-21 19:07:35 +03:00
ivan tkachenko 39a8255532 Fix LethalConfig dependency string
Apparently, this is different from BepInEx plugin GUID.
2025-07-21 02:06:14 +03:00
ivan tkachenko b7eb4ce60b Update README 2025-07-21 01:56:49 +03:00
ivan tkachenko d6a2bf21b1 Bump version 2025-07-21 01:13:40 +03:00
ivan tkachenko 730f125d62 Patch Jester destructor to reset the light show
It is needed to despawn Jester via Imperium's Object Explorer.
2025-07-21 01:06:45 +03:00
ivan tkachenko 8e065d3e51 Add config option to skip tracks marked as Explicit Content/Lyrics
Unfortunately it is configurable by host only, and there is no sane way
to make work from clients.
2025-07-21 00:55:40 +03:00
ivan tkachenko 2a33457661 Harmony: Use nameof() instead of hardcoded strings 2025-07-21 00:32:43 +03:00
ivan tkachenko 0fbf0b04f4 Add V70PoweredLights_Fix to the package dependencies
Not strictly required, but makes this mod shine brighter.
2025-07-21 00:32:43 +03:00
ivan tkachenko 0c5d4f7158 Add DiscoBall to Main on all interiors, BirthdayRoom and factory (belt room) 2025-07-21 00:32:43 +03:00
ivan tkachenko 9e066372c5 Add support for lyrics randomization 2025-07-21 00:32:42 +03:00
ivan tkachenko ca977625db Sort imports the way VisualStudio likes it
Apparently, Sublime Text's Sort Lines command ordered them in a weird
way, inconsistent with VS, VS Code and human logic.
2025-07-20 23:04:41 +03:00
ivan tkachenko 7d1cac6e2e Add lyrics, flickering and fade out transitions to many tracks 2025-07-20 23:04:40 +03:00
ivan tkachenko 2229fa3545 Add debug-only config for lyrics time series 2025-07-20 23:04:40 +03:00
ivan tkachenko 118eecbb59 Add support for fading out, and debug-only config for flickering lights 2025-07-20 23:04:40 +03:00
ivan tkachenko b8824dbbfb Config: Most synced options have something in common 2025-07-20 23:04:40 +03:00
ivan tkachenko 3e751c0d8d Config: reduce repetition
It may look complicated, but it reduced references to each individual
entry from almost ten to just 4.
2025-07-20 23:04:39 +03:00
ivan tkachenko 601ecf8887 Reworked state management system, automatic wrapping of timestamps and spans
Add lyrics for MoyaZhittya
2025-07-20 23:04:39 +03:00
ivan tkachenko d13c617895 Apply audio offsets early to simplify math 2025-07-18 02:40:55 +03:00
ivan tkachenko e1f19b3919 Add track Kach with custom palette and timings 2025-07-18 02:40:55 +03:00
ivan tkachenko ba0162b3e1 Add track PWNED with custom palette and timings 2025-07-18 02:40:54 +03:00
ivan tkachenko ed8804b7a7 Add track Chereshnya with custom palette and timings 2025-07-18 02:40:53 +03:00
ivan tkachenko 9be9eaaf80 Extend loop of the track VseVZale
Now includes second phase OOOoooo OOooo
2025-07-18 02:40:53 +03:00
ivan tkachenko 0683a18491 Port track VseVZale to OGG format
No gap now.
2025-07-18 02:40:52 +03:00
ivan tkachenko 6204888453 Port track DeployDestroy to OGG format
No gap now.
2025-07-18 02:40:52 +03:00
ivan tkachenko c15637b347 Port track Durochka to OGG format, add custom transitions
No gap now.
2025-07-18 02:40:51 +03:00
ivan tkachenko 42c1f29a16 Port track Gorgorod to OGG format
No gap now.
2025-07-18 02:40:50 +03:00
ivan tkachenko 8a193fa408 Port track MoyaZhittya to OGG format
No gap now.
2025-07-18 02:40:50 +03:00
ivan tkachenko 4ee20adea7 Port track MuzikaGromche to OGG format
Twice as longer, loops better, no gap.
2025-07-18 02:40:49 +03:00
ivan tkachenko 2df7d28d43 New operators for Palette
With these it would be easier to create more complicated timelines
without repeating yourself over and over again.
2025-07-18 02:40:49 +03:00
ivan tkachenko 43d1565dbe MSBuild: Add platform-agnostic task to convert WAV to OGG 2025-07-18 02:40:48 +03:00
ivan tkachenko f5dab20d67 Add track Yalgaar with custom palette and timings 2025-07-18 02:40:48 +03:00
ivan tkachenko 38cfb5f5e7 Add track Peretasovka with custom palette and timings 2025-07-18 02:40:47 +03:00
ivan tkachenko b86c50a848 Add track Song2 with custom palette and timings 2025-07-18 02:40:47 +03:00
ivan tkachenko 694bc61dae Add tracks GodMode and RiseAndShine with custom palette and timings 2025-07-18 02:40:46 +03:00
ivan tkachenko 909efa720f Add track ZmeiGorynich with custom palette and timings 2025-07-18 02:36:43 +03:00
ivan tkachenko a8761bf679 Add support for interpolated color transitions for lights, with debug-only synced overrides 2025-07-17 22:36:52 +03:00
ivan tkachenko ad77530b6d Add support for per-track palettes, and debug-only synced palette override
Palettes are contributed by @REALJUSTNOTHING
2025-07-17 22:35:19 +03:00
ivan tkachenko 34d8da1562 Add configurable global audio offset, useful for Bluetooth headsets 2025-07-17 22:35:19 +03:00
ivan tkachenko b73c7ee3cb Sync playback to the actual beat count rather than relying on BPM 2025-07-17 22:34:38 +03:00
ivan tkachenko 0d4f180a37 Add debug-only ability to change weights of tracks while on a moon
And drop obsoleted debug code. With the new on-the-fly track weights
configuration, hardcoding one in build is not necessary anymore.
2025-07-16 03:06:43 +03:00
ivan tkachenko 829c44e347 Add debug-only synced config option to skip wind-up phase 2025-07-16 03:06:42 +03:00
ivan tkachenko b15e93ac34 Factor out CSync hack into a separate method
We gonna register more synced entries in debug-only builds, but marking
nullable fields with the [SyncedEntryField] attribute is not an option.
2025-07-15 22:47:02 +03:00
ivan tkachenko f158e7728c Fix language section toggle for non-host
There is no point in checking for synchronized value before flipping
local value.
2025-07-15 21:51:38 +03:00
ivan tkachenko 2b42899779 Reorder some statements to make them visually more grouped together
Postfix patch went from 5 if-blocks down to only 3 \o/

There is no need to stop the creatureVoice and start it delayed in two
separate condition blocks. Also, the code should only rely on state
transitions, and not on AudioSource.isPlaying property.
2025-07-14 14:44:17 +03:00
251 changed files with 25285 additions and 341 deletions

15
.editorconfig Normal file
View File

@ -0,0 +1,15 @@
[*.cs]
# IDE0290: Use primary constructor
# Primary constructors are far from perfect: they can't have readonly fields, while fields can be used anywhere in the class body.
csharp_style_prefer_primary_constructors = false
# IDE0305: Simplify collection initialization
dotnet_style_prefer_collection_expression = never
# IDE0031: Use null propagation
# Unity overrides equality operator, so gameObject == null also accounts for internal state of the backing C++ object
# Read more:
# - https://blog.lslabs.dev/posts/null_check_equality_unity
# - https://blog.lslabs.dev/posts/unity_script_duality
dotnet_style_null_propagation = false

9
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,9 @@
{
"recommendations": [
"Vue.volar",
"vitest.explorer",
"dbaeumer.vscode-eslint",
"EditorConfig.EditorConfig",
"esbenp.prettier-vscode"
]
}

103
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,103 @@
{
// https://github.com/tailwindlabs/tailwindcss/discussions/5258#discussioncomment-1979394
"css.customData": [
".vscode/tailwind.json"
],
// Disable the default formatter, use eslint instead
"prettier.enable": false,
"editor.formatOnSave": false,
// Auto fix
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never"
},
// Silent the stylistic rules in your IDE, but still auto fix them
"eslint.rules.customizations": [
{
"rule": "style/*",
"severity": "off",
"fixable": true
},
{
"rule": "format/*",
"severity": "off",
"fixable": true
},
{
"rule": "*-indent",
"severity": "off",
"fixable": true
},
{
"rule": "*-spacing",
"severity": "off",
"fixable": true
},
{
"rule": "*-spaces",
"severity": "off",
"fixable": true
},
{
"rule": "*-order",
"severity": "off",
"fixable": true
},
{
"rule": "*-dangle",
"severity": "off",
"fixable": true
},
{
"rule": "*-newline",
"severity": "off",
"fixable": true
},
{
"rule": "*quotes",
"severity": "off",
"fixable": true
},
{
"rule": "*semi",
"severity": "off",
"fixable": true
}
],
// Enable eslint for all supported languages
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"html",
"markdown",
"json",
"jsonc",
"yaml",
"toml",
"xml",
"gql",
"graphql",
"astro",
"svelte",
"css",
"less",
"scss",
"pcss",
"postcss"
],
"workspaceKeybindings.manimPreviewTask.enabled": true,
"typescript.format.enable": false,
"typescript.tsdk": "./Frontend/node_modules/typescript/lib",
"[vue]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[typescript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[javascript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
}
}

95
.vscode/tailwind.json vendored Normal file
View File

@ -0,0 +1,95 @@
{
"version": 4.0,
"atDirectives": [
{
"name": "@theme",
"description": "Use the `@theme` directive to define your project's custom design tokens, like fonts, colors, and breakpoints.",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#theme-directive"
}
]
},
{
"name": "@source",
"description": "Use the `@source` directive to explicitly specify source files that aren't picked up by Tailwind's automatic content detection.",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#source-directive"
}
]
},
{
"name": "@utility",
"description": "Use the `@utility` directive to add custom utilities to your project that work with variants like `hover`, `focus` and `lg`.",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#utility-directive"
}
]
},
{
"name": "@variant",
"description": "Use the `@variant` directive to apply a Tailwind variant to styles in your CSS.",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#variant-directive"
}
]
},
{
"name": "@custom-variant",
"description": "Use the `@custom-variant` directive to add a custom variant in your project.",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#custom-variant-directive"
}
]
},
{
"name": "@apply",
"description": "Use the `@apply` directive to inline any existing utility classes into your own custom CSS.",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#apply-directive"
}
]
},
{
"name": "@reference",
"description": "If you want to use `@apply` or `@variant` in the `<style>` block of a Vue or Svelte component, or within CSS modules, you will need to import your theme variables, custom utilities, and custom variants to make those values available in that context.\n\nTo do this without duplicating any CSS in your output, use the `@reference` directive to import your main stylesheet for reference without actually including the styles.",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#reference-directive"
}
]
},
{
"name": "@config",
"description": "Use the `@config` directive to load a legacy JavaScript-based configuration file.",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#config-directive"
}
]
},
{
"name": "@plugin",
"description": "Use the `@plugin` directive to load a legacy JavaScript-based plugin.",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#plugin-directive"
}
]
}
]
}

69
AGENTS.md Normal file
View File

@ -0,0 +1,69 @@
# Muzika Gromche — AI Agent Guide
## Overview
- **Purpose**: This repository builds a BepInEx plugin (C#) that adds synchronized party music + light effects to Lethal Company, plus a small frontend playground for track metadata and browsing.
- **Two main parts**: the core plugin in `MuzikaGromche/` (targets `netstandard2.1`) and the frontend in `Frontend/` (Vite 3 + Vue + Vitest).
- **Tools and helpers**: there are some helpful Python scripts in the `playground` directory.
## What to edit / hotspots
- `MuzikaGromche/Plugin.cs`: plugin entry and initial configuration registration.
- `MuzikaGromche/*.cs` (e.g. `PoweredLights.cs`, `DiscoBallManager.cs`, `SpawnRateManager.cs`, `ScreenFiltersManager.cs`): main game integration and effect logic.
- `UnityAssets/` and `MuzikaGromche/bin/...`: Unity assets and compiled outputs used for packaging.
- Frontend audio/metadata: `Frontend/src/audio/AudioEngine.ts` and `Frontend/public/*` (track lists and audio bundles).
- Sources of audio tracks are edited and mixed outside of this repo, and only final deliveries are checked in here.
## Build & run (developer workflow)
- Primary helper: `Justfile` (root) and `MuzikaGromche.just.user` (root, not checked into the repo, so some commands may be unavailable). Common recipes:
- `just build` — runs both `build-debug` and `build-release` (calls `dotnet build`).
- `just build-release``dotnet build --configuration Release`.
- `just build-debug``dotnet build --configuration Debug`.
- `just build-debug run` — build & run the game for testing, most commonly used combination.
- `just install-imperium` — installs `dist/MuzikaGromche-Debug.zip` into an r2modman/Imperium profile path (see `Justfile` for `plugin_dir`). Not needed, as it is a post-build step anyway.
- `just ogg <track_name>` and `just ogg1 <track_name>` — custom msbuild targets that convert wav→ogg via `dotnet msbuild /t:wav2ogg` (used when adding tracks from outside of this repo).
- `just loud <track_name>` — runs a Python script that measures loudness of an audio track in LUFS, useful to calculate volume adjustments for normalization to a consistent desirable level.
- `just oggloud1 <track_name>` and `just oggloud <track_name>` — convert and measure loudness in one command invocation (single track, and intro+loop pair of tracks respectively).
- Frontend: in `Frontend/`:
- Use `pnpm` (lockfile `pnpm-lock.yaml` present). Run `pnpm install`.
- Dev: `pnpm run dev` (Vite). Build: `pnpm run build`.
- Test: `pnpm run test:browser` or `pnpm run coverage`. Uses Vitest with unified config in `vite.config.ts`.
- Python scripts in `playground`:
- Use `uv` tool to run Python code, or corresponding `just` targets if available.
## Packaging and outputs
- Plugin target: `netstandard2.1` — compiled DLLs appear under `MuzikaGromche/bin/<Configuration>/netstandard2.1/`.
- The repo expects a `dist/` zip for quick install (see `Justfile` `install-imperium` target). Look for `dist/MuzikaGromche-Debug.zip` when installing into a profile.
## Conventions & patterns
- BepInEx plugin pattern: follow `Plugin.cs` for how features are registered and how configuration entries are declared.
- Prefer small localized changes: keep public APIs stable and avoid broad refactors across many `*.cs` files without tests. The game integration is timing-sensitive.
- Manual testing is done by running the game (see `Justfile` `run` target).
- Track assets: audio tracks and timings are curated; if you add tracks, use the `just ogg` or `dotnet msbuild` tasks to convert. Run the game once, so that it dumps a new JSON metadata under the frontend `public/` directory to ensure that data stays in sync.
## Integration points & external dependencies
- Game modding: integrates with Lethal Company via BepInEx. The repo assumes you understand how to drop plugin DLLs into r2modman profiles (see `Justfile` `plugin_dir`).
- External tools: `dotnet` (SDK for building and custom msbuild targets), `just` (task runner) — commands are invoked from repository root; `pnpm`/`node` (frontend) — commands are invoked from `Frontend` directory.
## Examples to reference
- Change visual effects: edit `MuzikaGromche/PoweredLights.cs` or `MuzikaGromche/ScreenFiltersManager.cs` and test by running `just build-debug run`.
- Add frontend metadata: update `Frontend/src/assets/MuzikaGromcheTracks.json` and run `pnpm run build`.
## What NOT to assume
- There are no automated unit tests in the C# mod; it is unreasonably hard to run mod's code outside of Unity runtime, so don't bother with it. Validate changes with local builds and by installing into an r2modman profile.
- Packaging and profile paths are user-specific — `Justfile` contains a template `plugin_dir` that uses `$HOME` and `imperium_profile` fields; do not hardcode absolute paths in commits.
## Where to look next (quick links)
- `Justfile` and `MuzikaGromche.just.user` — primary developer recipes and packaging helpers.
- `MuzikaGromche/` — all plugin source code.
- `UnityAssets/` — art/animator resources, treat them as opaque binary blobs.
- `Frontend/` — frontend app, `src/audio/AudioEngine.ts` for audio logic.

BIN
Assets/ArcaneIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/ArcaneLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/AttentionPls1Intro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/AttentionPls2Intro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/AttentionPlsLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/BbIXODaHETIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/BbIXODaHETLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/BeefLiver1Intro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/BeefLiver3Intro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/BeefLiver4Intro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/BeefLiver4Loop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/BeefLiverLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/Beha1Intro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/Beha2Intro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/Beha3Intro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/BehaLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/ChereshnyaIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/ChereshnyaLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/DeployDestroyIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/DeployDestroyLoop.mp3 (Stored with Git LFS)

Binary file not shown.

BIN
Assets/DeployDestroyLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/DeployDestroyStart.mp3 (Stored with Git LFS)

Binary file not shown.

BIN
Assets/DiscoKapotIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/DiscoKapotLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/DurochkaIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/DurochkaLoop.mp3 (Stored with Git LFS)

Binary file not shown.

BIN
Assets/DurochkaLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/DurochkaStart.mp3 (Stored with Git LFS)

Binary file not shown.

BIN
Assets/GodModeIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/GodModeLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/GorgorodIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/GorgorodLoop.mp3 (Stored with Git LFS)

Binary file not shown.

BIN
Assets/GorgorodLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/GorgorodStart.mp3 (Stored with Git LFS)

Binary file not shown.

BIN
Assets/HighLowIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/HighLowLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/IkWilJeIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/IkWilJeLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/KachIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/KachLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/MoyaZhittyaIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/MoyaZhittyaLoop.mp3 (Stored with Git LFS)

Binary file not shown.

BIN
Assets/MoyaZhittyaLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/MoyaZhittyaStart.mp3 (Stored with Git LFS)

Binary file not shown.

BIN
Assets/MuzikaGromcheIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/MuzikaGromcheLoop.mp3 (Stored with Git LFS)

Binary file not shown.

BIN
Assets/MuzikaGromcheLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/MuzikaGromcheStart.mp3 (Stored with Git LFS)

Binary file not shown.

BIN
Assets/OnePartiyaUdarIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/OnePartiyaUdarLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/PWNEDIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/PWNEDLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/PaardenIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/PaardenLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/PeretasovkaIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/PeretasovkaLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/PickUpSticks1Intro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/PickUpSticks2Intro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/PickUpSticksLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/ReelGoonIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/ReelGoonLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/RiseAndShineIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/RiseAndShineLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/Song2Intro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/Song2Loop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/TwoFastTuFuriousIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/TwoFastTuFuriousLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/VseVZaleIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/VseVZaleLoop.mp3 (Stored with Git LFS)

Binary file not shown.

BIN
Assets/VseVZaleLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/VseVZaleStart.mp3 (Stored with Git LFS)

Binary file not shown.

BIN
Assets/WhistleIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/WhistleLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/YalgaarIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/YalgaarLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/ZmeiGorynichIntro.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Assets/ZmeiGorynichLoop.ogg (Stored with Git LFS) Normal file

Binary file not shown.

128
CHANGELOG.md Normal file
View File

@ -0,0 +1,128 @@
# Changelog
## MuzikaGromche 1337.9001.69
- Show real Artist & Song info in the config.
## MuzikaGromche 1337.9001.68 - LocalHost hotfix
- Fixed occasionally broken playback of v1337.9001.67, sorry about that.
- Turns out, client-side vanilla-compat mode can never be perfectly timed, so don't expect much without a modded host.
- Removed an existing track Yalgaar.
- Merged two config options into one: Reduce Visual Effects & Display Lyrics.
- Added a new track Arcane.
## MuzikaGromche 1337.9001.67 - LocalHost Edition
- Added a new track TwoFastTuFurious (from the same artist as PickUpSticks), thematic to the upcoming Valentine's Day.
- Added support for client-side playback while playing with an unmodded/vanilla host.
- Tweaked the amount of visual flare at the Factory's start room (main tile).
## MuzikaGromche 1337.9001.4 - v73 Chinese New Year Edition
- Remastered recently added track IkWilJe using a higher quality source audio and better fitting visual effects.
- Adjusted lyrics for PWNED (can't believe it missed an obvious joke).
- Added a new track Paarden.
- Added a new track DiscoKapot.
- Added an accessibility option to reduce the intensity of overly distracting visual effects.
- Seasonal content like New Year's songs (IkWilJe, Paarden, DiscoKapot) will only be available for selection during their respective seasons.
- Reduced memory usage by almost 400 MB, thanks to loading audio clips on demand (not preloading all tracks at launch).
- Added a new track PickUpSticks.
## MuzikaGromche 1337.9001.3 - v73 Happy New Year Edition
- Added a new track IkWilJe.
## MuzikaGromche 1337.9001.2 - v73 Rushed Edition
- Added a new track HighLow.
## MuzikaGromche 1337.9001.1 - v73 Music louder Edition
- Raised the default audio volume, and added a configuration slider.
- Tweaked color palette, lyrics and visual effects for MoyaZhittya and some other tracks.
## MuzikaGromche 1337.9001.0 - v73 Music quieter Edition
- Updated netcode-patch to support Lethal Company v73.
- Remastered all the audio tracks to target a consistent loudness level which allows you hear your teammates.
- Remastered track Song2 to fix cut points.
- Shortened intro of track Peretasovka to match vanilla timings.
- Added multiple intro variants for BeefLiver.
- Added a new track BbIXODaHET.
- Added a new track Whistle. Now it can fully replace WhistleJester!
- Added a new track ReelGoon.
## MuzikaGromche 1337.420.9004 - Life Support Edition
- Override Death Screen / Game Over text in certain cases.
- Added a new track AttentionPls featuring multiple intro variants and new visual effects.
## MuzikaGromche 1337.420.9003 - Lights Out Edition
- Fixed wrong colors during fade out transition, e.g. in Mineshaft tunnel tiles.
## MuzikaGromche 1337.420.9002 - Anime Edition
- Added a new track OnePartiyaUdar in Japanese language.
- Remastered recently added tracks at conventional 44100 Hz for better stitching.
- Improved playback experience: use precise DSP time and up-front scheduing for seamless audio stitching, add custom Audio Sources to improve reliability.
- Removed remaining CSync code and package references even from debug builds.
- Downgraded LobbyCompatibility to optional dependency.
- Toggled config option to increase certain spawn rate to ON by default.
- Fixed resetting to wrong initial colors, e.g. in Mineshaft tunnel tiles.
## MuzikaGromche 1337.420.9001 - Multiverse Edition
- Added support for tracks to rotate between multiple audio variants during a round.
- Added a new track Beha with three different variants of intro.
## MuzikaGromche 1337.420.69 - It's All DiscoNnected Edition
- Fixed harmless but annoying errors in BepInEx console output.
- Improve smoothness of color animations.
- Added a new track BeefLiver.
## MuzikaGromche 1337.69.420 - It's All Connected Edition
- Fix certain object hanging around after being disabled.
- CSync proved to be unreliable for config syncing, so rewrote track selection to custom netcode.
## MuzikaGromche 13.37.9001 - Chromaberrated Edition
- Fixed more missing flickering behaviours for some animators controllers.
- Fixed some powered lights not fully turning off or flickering when there are multiple Light components per container.
- Improved performance by pre-loading certain assets at the start of round instead of at a timing-critical frame update.
- Added an opt-in config option to increase certain spawn rate to experience content of this mod more often.
## MuzikaGromche 13.37.1337 - Photosensitivity Warning Edition
- Added LobbyCompatibility to dependencies to avoid desync issues.
- Fixed lyrics not being displayed in some situations.
- Fixed visual issues with the fade out effect.
- Fixed visual glitch at the last beat of a loop.
- Fixed timings of one of the tracks.
- Removed unnecessary "Enable Color Animations" config option.
- Fixed missing flickering behaviours for some animators controllers.
## MuzikaGromche 13.37.911 - Sri Lanka Bus hotfix
- Fixed certain event sometimes not working due to wrong method call.
- Added support for pre-v70 Mansion Main tile.
## MuzikaGromche 13.37.420 - Sri Lanka Bus Edition
Completely rewritten by Ratijas, with tons of new content.
- Added lots of new tracks.
- Fixed gaps in old tracks.
- New code synchronizes light show to the beat.
- Timings, animation curves, color palettes and events fine-tuned for each track by visual artist [Just Nothing](https://t.me/REALJUSTNOTHING).
- Configurable Audio Delay for those with Bluetooth headset.
- Configurable chance of randomly choosing each tracks.
- Added lyrics to *some* of the tracks, and a configuration toggle.
- Certain tiles are patched by [WaterGun](https://www.youtube.com/channel/UCCxCFfmrnqkFZ8i9FsXBJVA) to add some visual flare.
## MuzikaGromche 13.37.6 - Christmas Special
Last known version released by Oflor. Added special timed content for New Year and Christmas.

5
Directory.Build.targets Normal file
View File

@ -0,0 +1,5 @@
<Project>
<Target Name="NetcodePatch" AfterTargets="PostBuildEvent">
<Exec Command="dotnet netcode-patch -uv 2022.3.62 -nv 1.12.0 &quot;$(TargetPath)&quot; @(ReferencePathWithRefAssemblies->'&quot;%(Identity)&quot;', ' ')"/>
</Target>
</Project>

8
Frontend/.editorconfig Normal file
View File

@ -0,0 +1,8 @@
[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}]
charset = utf-8
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
end_of_line = lf
max_line_length = 100

55
Frontend/.gitignore vendored Normal file
View File

@ -0,0 +1,55 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
.env
.cache
dist
.idea
.vite-node
ltex*
.DS_Store
.zed
# tests & coverage
coverage
.vitest-reports
*.tsbuildinfo
# exclude static html reporter folder
test/browser/html/
test/core/html/
.vitest-attachments
explainFiles.txt
.vitest-dump
# ESLint
.eslintcache
# Vite CSS Modules
*.module.css.d.ts
# Project assets
/public/MuzikaGromcheAudio/*
!/public/MuzikaGromcheAudio/.gitkeep

39
Frontend/README.md Normal file
View File

@ -0,0 +1,39 @@
# Muzika Gromche — Web Player & Editor
Play your favorite tracks on repeat right in your browser.
## Project structure
The look & feel is inspired by a certain popular NLE (Non-Linear video Editor) which incorporates DAW (Digital Audio Workstation) functionality in it.
- Library page lists all available audio tracks with some basic information presented in cards. There is a search / filter field on top.
- Player page features in-depth information about selected audio track, a dedicated timeline widget lets you play, seek, scrub, zoom into timeline tracks & clips, and manupulate them. Each timeline track represents either a segment of the song (intro, loop), or a specific kind of visual effects (such as flickering, fading out & color palette for powered lights, lyrics, drunkness & condensation).
## Development
### Adding new tracks
1. Add track declaration to Plugin.cs and fill in its properties.
2. Launch the game once, so that it generates a new JSON dump (in the Lethal Company save files directory) of all tracks.
3. Replace `src/assets/MuzikaGromcheTracks.json` with the new JSON dump.
4. Discard lines with IP address and username or replace them with generic ones.
### Run & test
First time setup:
- copy audio files from the `/Assets/` directory located at repository's root to `Frontend/public/MuzikaGromcheAudio/` directory.
Muzika Gromche Web Player & Editor is built with Vue 3 + TypeScript + Vite.
```sh
pnpm run dev
pnpm run test
```
### Deploy
```sh
pnpm run build
```
Use scp, rsync or any other tool to upload content of `dist/` to root@ratijas.me `/var/www/html/muzika-gromche/`.

2
Frontend/env.d.ts vendored Normal file
View File

@ -0,0 +1,2 @@
/// <reference types="vite/client" />
/// <reference types="vite-svg-loader" />

19
Frontend/eslint.config.ts Normal file
View File

@ -0,0 +1,19 @@
import antfu from '@antfu/eslint-config'
export default antfu({
lessOpinionated: true,
ignores: [
'src/assets/MuzikaGromcheTracks.json',
],
rules: {
'default-case-last': 'off',
'pnpm/json-enforce-catalog': 'off',
'pnpm/yaml-enforce-settings': 'off',
'ts/consistent-type-definitions': 'off',
'no-console': 'off',
// who said I can't pass refs inside objects as props?
'vue/no-mutating-props': ['error', {
shallowOnly: true,
}],
},
})

15
Frontend/index.html Normal file
View File

@ -0,0 +1,15 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="icon" href="/icon-32.png" sizes="32x32" type="image/png">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Muzika Gromche — The ultimate Jester party music mod</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

62
Frontend/package.json Normal file
View File

@ -0,0 +1,62 @@
{
"name": "muzika-gromche-frontend",
"type": "module",
"version": "0.0.0",
"private": true,
"packageManager": "pnpm@10.28.1+sha512.7d7dbbca9e99447b7c3bf7a73286afaaf6be99251eb9498baefa7d406892f67b879adb3a1d7e687fc4ccc1a388c7175fbaae567a26ab44d1067b54fcb0d6a316",
"scripts": {
"dev": "vite",
"build": "run-p type-check prebuild \"build-only {@}\" --",
"prebuild": "tsx scripts/generate-icons.ts",
"build-only": "vite build",
"preview": "vite preview",
"test": "vitest",
"coverage": "vitest run --coverage",
"type-check": "vue-tsc --build",
"lint": "eslint . --cache",
"lint:fix": "eslint . --cache --fix"
},
"dependencies": {
"@material-design-icons/svg": "^0.14.15",
"@tailwindcss/vite": "^4.1.18",
"@unhead/vue": "^2.1.2",
"@vueuse/core": "^14.1.0",
"mitt": "^3.0.1",
"pinia": "^3.0.4",
"tailwindcss": "^4.1.18",
"vue": "^3.5.27",
"vue-router": "^4.6.4"
},
"devDependencies": {
"@antfu/eslint-config": "^6.7.3",
"@tsconfig/node24": "^24.0.4",
"@types/jsdom": "^27.0.0",
"@types/node": "^24.10.9",
"@vitejs/plugin-vue": "^6.0.3",
"@vitest/browser-playwright": "^4.0.18",
"@vitest/coverage-v8": "4.0.15",
"@vitest/eslint-plugin": "^1.6.6",
"@vue/eslint-config-prettier": "^10.2.0",
"@vue/eslint-config-typescript": "^14.6.0",
"@vue/test-utils": "^2.4.6",
"@vue/tsconfig": "^0.8.1",
"eslint": "~9.39.2",
"eslint-plugin-format": "^1.3.1",
"eslint-plugin-vue": "~10.6.2",
"jiti": "^2.6.1",
"jsdom": "^27.4.0",
"npm-run-all2": "^8.0.4",
"png-to-ico": "^3.0.1",
"prettier": "^3.8.1",
"sharp": "^0.33.5",
"tsx": "^4.21.0",
"typescript": "~5.9.3",
"vite": "npm:rolldown-vite@^7.3.1",
"vite-css-modules": "^1.12.0",
"vite-plugin-vue-devtools": "^8.0.5",
"vite-svg-loader": "^5.1.0",
"vitest": "^4.0.18",
"vitest-browser-vue": "^2.0.2",
"vue-tsc": "^3.2.3"
}
}

7203
Frontend/pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
catalogMode: manual
shellEmulator: true
trustPolicy: no-downgrade
trustPolicyExclude:
- semver@6.3.1
- undici-types@6.21.0
onlyBuiltDependencies:
- esbuild
- sharp

View File

@ -0,0 +1 @@
Copy /Assets/ to this directory.

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

BIN
Frontend/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

BIN
Frontend/public/icon-32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,51 @@
import { promises as fs } from 'node:fs'
import path from 'node:path'
import process from 'node:process'
import { fileURLToPath } from 'node:url'
import toIco from 'png-to-ico'
import sharp from 'sharp'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const sourceIcon = path.resolve(__dirname, '../../icon.png')
const outputDir = path.resolve(__dirname, '../public')
async function generateIcons() {
await fs.mkdir(outputDir, { recursive: true })
// Generate PNGs
const sizes = [32, 192, 256]
for (const size of sizes) {
const outputPath = path.join(outputDir, `icon-${size}.png`)
await sharp(sourceIcon)
.resize(size, size)
.toFile(outputPath)
console.log(`Generated ${outputPath}`)
}
// Generate apple-touch-icon
const appleIconPath = path.join(outputDir, 'apple-touch-icon.png')
await sharp(sourceIcon)
.resize(180, 180)
.toFile(appleIconPath)
console.log(`Generated ${appleIconPath}`)
// Generate favicon.ico
const icoSizes = [16, 24, 32, 48]
const buffers = await Promise.all(icoSizes.map(size =>
sharp(sourceIcon)
.resize(size, size)
.png()
.toBuffer(),
))
const icoBuffer = await toIco(buffers)
const icoPath = path.join(outputDir, 'favicon.ico')
await fs.writeFile(icoPath, icoBuffer)
console.log(`Generated ${icoPath}`)
}
generateIcons().catch((err) => {
console.error(err)
process.exit(1)
})

Some files were not shown because too many files have changed in this diff Show More