Move piano glue behind behavior registry
This commit is contained in:
@@ -77,6 +77,27 @@ export class ItemBehaviorRegistry {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns whether any item-owned mode supports opening the command palette. */
|
||||
canOpenModeCommandPalette(mode: GameMode): boolean {
|
||||
for (const behavior of this.behaviors) {
|
||||
if (behavior.canOpenModeCommandPalette?.(mode)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Resolves an optional suspended mode that still wants key-up events while another overlay is active. */
|
||||
getModeKeyUpTarget(activeMode: GameMode, returnMode: GameMode): GameMode | null {
|
||||
for (const behavior of this.behaviors) {
|
||||
const target = behavior.getModeKeyUpTarget?.(activeMode, returnMode);
|
||||
if (target) {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Returns palette-visible commands for the active item-owned mode, if any. */
|
||||
getModeCommands(mode: GameMode): CommandDescriptor[] {
|
||||
const commands: CommandDescriptor[] = [];
|
||||
@@ -99,24 +120,20 @@ export class ItemBehaviorRegistry {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Routes incoming item-piano-note packets to the item behavior owning that protocol. */
|
||||
onRemotePianoNote(message: Extract<IncomingMessage, { type: 'item_piano_note' }>): void {
|
||||
/** Gives item behaviors a chance to consume custom incoming packets. */
|
||||
onIncomingMessage(message: IncomingMessage): boolean {
|
||||
for (const behavior of this.behaviors) {
|
||||
behavior.onRemotePianoNote?.(message);
|
||||
if (behavior.onIncomingMessage?.(message)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Routes incoming item-piano-status packets to behavior modules that track piano runtime state. */
|
||||
onPianoStatus(message: Extract<IncomingMessage, { type: 'item_piano_status' }>): void {
|
||||
/** Notifies behaviors that a peer left so they can release sender-owned runtime state. */
|
||||
onPeerLeft(senderId: string): void {
|
||||
for (const behavior of this.behaviors) {
|
||||
behavior.onPianoStatus?.(message);
|
||||
}
|
||||
}
|
||||
|
||||
/** Stops all remote notes for one sender across behavior modules that own remote note runtimes. */
|
||||
stopAllRemoteNotesForSender(senderId: string): void {
|
||||
for (const behavior of this.behaviors) {
|
||||
behavior.onStopAllRemoteNotesForSender?.(senderId);
|
||||
behavior.onPeerLeft?.(senderId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,9 +31,6 @@ export function createPianoBehavior(deps: ItemBehaviorDeps): ItemBehavior {
|
||||
}
|
||||
return true;
|
||||
},
|
||||
onPianoStatus: (message) => {
|
||||
controller.onPianoStatus(message);
|
||||
},
|
||||
onPropertyPreviewChange: (item, key, value) => {
|
||||
controller.onPreviewPropertyChange(item, key, value);
|
||||
},
|
||||
@@ -50,6 +47,12 @@ export function createPianoBehavior(deps: ItemBehaviorDeps): ItemBehavior {
|
||||
controller.handleModeKeyUp(input);
|
||||
return true;
|
||||
},
|
||||
canOpenModeCommandPalette: (mode) => mode === 'pianoUse',
|
||||
getModeKeyUpTarget: (activeMode, returnMode) => {
|
||||
if (activeMode === 'pianoUse') return 'pianoUse';
|
||||
if (activeMode === 'commandPalette' && returnMode === 'pianoUse') return 'pianoUse';
|
||||
return null;
|
||||
},
|
||||
getModeCommands: (mode) => {
|
||||
if (mode !== 'pianoUse') return [];
|
||||
return controller.getModeCommands();
|
||||
@@ -58,29 +61,37 @@ export function createPianoBehavior(deps: ItemBehaviorDeps): ItemBehavior {
|
||||
if (mode !== 'pianoUse') return false;
|
||||
return controller.runModeCommand(commandId);
|
||||
},
|
||||
onRemotePianoNote: (message) => {
|
||||
if (message.on) {
|
||||
controller.playRemoteNote({
|
||||
itemId: message.itemId,
|
||||
senderId: message.senderId,
|
||||
keyId: message.keyId,
|
||||
midi: message.midi,
|
||||
instrument: message.instrument,
|
||||
voiceMode: message.voiceMode,
|
||||
octave: message.octave,
|
||||
attack: message.attack,
|
||||
decay: message.decay,
|
||||
release: message.release,
|
||||
brightness: message.brightness,
|
||||
x: message.x,
|
||||
y: message.y,
|
||||
emitRange: message.emitRange,
|
||||
});
|
||||
} else {
|
||||
controller.stopRemoteNote(message.senderId, message.keyId);
|
||||
onIncomingMessage: (message) => {
|
||||
if (message.type === 'item_piano_note') {
|
||||
if (message.on) {
|
||||
controller.playRemoteNote({
|
||||
itemId: message.itemId,
|
||||
senderId: message.senderId,
|
||||
keyId: message.keyId,
|
||||
midi: message.midi,
|
||||
instrument: message.instrument,
|
||||
voiceMode: message.voiceMode,
|
||||
octave: message.octave,
|
||||
attack: message.attack,
|
||||
decay: message.decay,
|
||||
release: message.release,
|
||||
brightness: message.brightness,
|
||||
x: message.x,
|
||||
y: message.y,
|
||||
emitRange: message.emitRange,
|
||||
});
|
||||
} else {
|
||||
controller.stopRemoteNote(message.senderId, message.keyId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (message.type === 'item_piano_status') {
|
||||
controller.onPianoStatus(message);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
onStopAllRemoteNotesForSender: (senderId) => {
|
||||
onPeerLeft: (senderId) => {
|
||||
controller.stopAllRemoteNotesForSender(senderId);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -32,9 +32,10 @@ export type ItemBehavior = {
|
||||
onWorldUpdate?: () => void;
|
||||
handleModeInput?: (mode: GameMode, input: ModeInput) => boolean;
|
||||
handleModeKeyUp?: (mode: GameMode, input: Pick<ModeInput, 'code' | 'shiftKey'>) => boolean;
|
||||
canOpenModeCommandPalette?: (mode: GameMode) => boolean;
|
||||
getModeKeyUpTarget?: (activeMode: GameMode, returnMode: GameMode) => GameMode | null;
|
||||
getModeCommands?: (mode: GameMode) => CommandDescriptor[];
|
||||
runModeCommand?: (mode: GameMode, commandId: string) => boolean;
|
||||
onRemotePianoNote?: (message: Extract<IncomingMessage, { type: 'item_piano_note' }>) => void;
|
||||
onPianoStatus?: (message: Extract<IncomingMessage, { type: 'item_piano_status' }>) => void;
|
||||
onStopAllRemoteNotesForSender?: (senderId: string) => void;
|
||||
onIncomingMessage?: (message: IncomingMessage) => boolean;
|
||||
onPeerLeft?: (senderId: string) => void;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user