Drive piano digit shortcuts from server instrument metadata
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
// Maintainer-controlled web client version.
|
// Maintainer-controlled web client version.
|
||||||
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
|
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
|
||||||
window.CHGRID_WEB_VERSION = "2026.02.25 R229";
|
window.CHGRID_WEB_VERSION = "2026.02.25 R230";
|
||||||
// Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid.
|
// Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid.
|
||||||
window.CHGRID_TIME_ZONE = "America/Detroit";
|
window.CHGRID_TIME_ZONE = "America/Detroit";
|
||||||
|
|||||||
@@ -15,6 +15,22 @@ export const PIANO_INSTRUMENT_OPTIONS = [
|
|||||||
|
|
||||||
export type PianoInstrumentId = (typeof PIANO_INSTRUMENT_OPTIONS)[number];
|
export type PianoInstrumentId = (typeof PIANO_INSTRUMENT_OPTIONS)[number];
|
||||||
|
|
||||||
|
/** Returns whether a runtime string is one of the supported piano instrument ids. */
|
||||||
|
export function isPianoInstrumentId(value: string): value is PianoInstrumentId {
|
||||||
|
return (
|
||||||
|
value === 'piano' ||
|
||||||
|
value === 'electric_piano' ||
|
||||||
|
value === 'guitar' ||
|
||||||
|
value === 'organ' ||
|
||||||
|
value === 'bass' ||
|
||||||
|
value === 'violin' ||
|
||||||
|
value === 'synth_lead' ||
|
||||||
|
value === 'brass' ||
|
||||||
|
value === 'nintendo' ||
|
||||||
|
value === 'drum_kit'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
type VoiceRuntime = {
|
type VoiceRuntime = {
|
||||||
gain: GainNode;
|
gain: GainNode;
|
||||||
panner: StereoPannerNode | null;
|
panner: StereoPannerNode | null;
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import {
|
import {
|
||||||
DEFAULT_PIANO_SETTINGS_BY_INSTRUMENT,
|
DEFAULT_PIANO_SETTINGS_BY_INSTRUMENT,
|
||||||
PIANO_INSTRUMENT_OPTIONS,
|
|
||||||
PianoSynth,
|
PianoSynth,
|
||||||
|
isPianoInstrumentId,
|
||||||
type PianoInstrumentId,
|
type PianoInstrumentId,
|
||||||
} from '../../../audio/pianoSynth';
|
} from '../../../audio/pianoSynth';
|
||||||
import { type IncomingMessage, type OutgoingMessage } from '../../../network/protocol';
|
import { type IncomingMessage, type OutgoingMessage } from '../../../network/protocol';
|
||||||
import { type GameMode, type WorldItem } from '../../../state/gameState';
|
import { type GameMode, type WorldItem } from '../../../state/gameState';
|
||||||
|
import { getItemPropertyOptionValues } from '../../itemRegistry';
|
||||||
|
|
||||||
const PIANO_WHITE_KEY_MIDI_BY_CODE: Record<string, number> = {
|
const PIANO_WHITE_KEY_MIDI_BY_CODE: Record<string, number> = {
|
||||||
KeyA: 60,
|
KeyA: 60,
|
||||||
@@ -321,8 +322,9 @@ export class PianoController {
|
|||||||
if (code.startsWith('Digit')) {
|
if (code.startsWith('Digit')) {
|
||||||
const digit = Number(code.slice(5));
|
const digit = Number(code.slice(5));
|
||||||
const instrumentIndex = digit === 0 ? 9 : digit - 1;
|
const instrumentIndex = digit === 0 ? 9 : digit - 1;
|
||||||
if (Number.isInteger(instrumentIndex) && instrumentIndex >= 0 && instrumentIndex < PIANO_INSTRUMENT_OPTIONS.length) {
|
const shortcutInstruments = this.getShortcutInstruments();
|
||||||
const instrument = PIANO_INSTRUMENT_OPTIONS[instrumentIndex];
|
if (Number.isInteger(instrumentIndex) && instrumentIndex >= 0 && instrumentIndex < shortcutInstruments.length) {
|
||||||
|
const instrument = shortcutInstruments[instrumentIndex];
|
||||||
if (instrument) {
|
if (instrument) {
|
||||||
const defaults = DEFAULT_PIANO_SETTINGS_BY_INSTRUMENT[instrument];
|
const defaults = DEFAULT_PIANO_SETTINGS_BY_INSTRUMENT[instrument];
|
||||||
const voiceMode = this.defaultsVoiceModeForInstrument(instrument);
|
const voiceMode = this.defaultsVoiceModeForInstrument(instrument);
|
||||||
@@ -646,18 +648,24 @@ export class PianoController {
|
|||||||
|
|
||||||
private normalizePianoInstrument(value: unknown): PianoInstrumentId {
|
private normalizePianoInstrument(value: unknown): PianoInstrumentId {
|
||||||
const raw = String(value ?? 'piano').trim().toLowerCase();
|
const raw = String(value ?? 'piano').trim().toLowerCase();
|
||||||
if (raw === 'electric_piano') return 'electric_piano';
|
if (isPianoInstrumentId(raw)) return raw;
|
||||||
if (raw === 'guitar') return 'guitar';
|
|
||||||
if (raw === 'organ') return 'organ';
|
|
||||||
if (raw === 'bass') return 'bass';
|
|
||||||
if (raw === 'violin') return 'violin';
|
|
||||||
if (raw === 'synth_lead') return 'synth_lead';
|
|
||||||
if (raw === 'brass') return 'brass';
|
|
||||||
if (raw === 'nintendo') return 'nintendo';
|
|
||||||
if (raw === 'drum_kit') return 'drum_kit';
|
|
||||||
return 'piano';
|
return 'piano';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getShortcutInstruments(): PianoInstrumentId[] {
|
||||||
|
const options = getItemPropertyOptionValues('piano', 'instrument') ?? [];
|
||||||
|
const normalized: PianoInstrumentId[] = [];
|
||||||
|
const seen = new Set<string>();
|
||||||
|
for (const option of options) {
|
||||||
|
const raw = option.trim().toLowerCase();
|
||||||
|
if (!isPianoInstrumentId(raw) || seen.has(raw)) continue;
|
||||||
|
seen.add(raw);
|
||||||
|
normalized.push(raw);
|
||||||
|
if (normalized.length >= 10) break;
|
||||||
|
}
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
private getPianoMidiForCode(code: string): number | null {
|
private getPianoMidiForCode(code: string): number | null {
|
||||||
if (code in PIANO_WHITE_KEY_MIDI_BY_CODE) {
|
if (code in PIANO_WHITE_KEY_MIDI_BY_CODE) {
|
||||||
return PIANO_WHITE_KEY_MIDI_BY_CODE[code]!;
|
return PIANO_WHITE_KEY_MIDI_BY_CODE[code]!;
|
||||||
|
|||||||
Reference in New Issue
Block a user