Support client interact action to allow updating of properties for non owning players
This commit is contained in:
@@ -142,22 +142,8 @@ export function createCardTableController(deps: CardTableControllerDeps): {
|
||||
deps.sfxUiCancel();
|
||||
return;
|
||||
}
|
||||
const card = drawPile[0];
|
||||
const newDrawPile = drawPile.slice(1);
|
||||
const hands = item.params['hands'];
|
||||
const handsObj: Record<string, string[]> =
|
||||
hands && typeof hands === 'object' && !Array.isArray(hands)
|
||||
? (hands as Record<string, string[]>)
|
||||
: {};
|
||||
const currentHand = Array.isArray(handsObj[nickname]) ? [...handsObj[nickname]] : [];
|
||||
currentHand.push(card);
|
||||
const newHands = { ...handsObj, [nickname]: currentHand };
|
||||
deps.signalingSend({
|
||||
type: 'item_update',
|
||||
itemId: item.id,
|
||||
params: { draw_pile: newDrawPile, hands: newHands },
|
||||
});
|
||||
deps.updateStatus(`Drew ${cardName(card)}. ${newDrawPile.length} cards remaining in pile.`);
|
||||
deps.signalingSend({ type: 'item_interact', itemId: item.id, action: 'draw' });
|
||||
deps.updateStatus('Drawing a card.');
|
||||
deps.sfxUiBlip();
|
||||
return;
|
||||
}
|
||||
@@ -292,58 +278,30 @@ export function createCardTableController(deps: CardTableControllerDeps): {
|
||||
|
||||
if (control.type === 'select') {
|
||||
const actionIdx = deps.state.cardTableCardActionIndex;
|
||||
const card = hand[cardIndex];
|
||||
const newHand = [...hand];
|
||||
newHand.splice(cardIndex, 1);
|
||||
|
||||
const hands = item.params['hands'];
|
||||
const handsObj: Record<string, string[]> =
|
||||
hands && typeof hands === 'object' && !Array.isArray(hands)
|
||||
? (hands as Record<string, string[]>)
|
||||
: {};
|
||||
|
||||
if (actionIdx === 0) {
|
||||
// Discard
|
||||
const discardPile = getDiscardPile(item);
|
||||
const newDiscard = [card, ...discardPile];
|
||||
const newHands = { ...handsObj, [nickname]: newHand };
|
||||
deps.signalingSend({
|
||||
type: 'item_update',
|
||||
type: 'item_interact',
|
||||
itemId: item.id,
|
||||
params: { discard_pile: newDiscard, hands: newHands },
|
||||
action: 'discard',
|
||||
params: { card_index: cardIndex },
|
||||
});
|
||||
deps.state.cardTableHandIndex = Math.min(cardIndex, Math.max(0, newHand.length - 1));
|
||||
if (newHand.length === 0) {
|
||||
deps.state.mode = 'cardTableMenu';
|
||||
deps.state.cardTableMenuIndex = 2; // view hand entry
|
||||
deps.updateStatus(`${cardName(card)} discarded. Hand is empty.`);
|
||||
} else {
|
||||
deps.state.mode = 'cardTableHand';
|
||||
deps.updateStatus(`${cardName(card)} discarded.`);
|
||||
}
|
||||
deps.state.mode = 'cardTableHand';
|
||||
deps.updateStatus('Discarding card.');
|
||||
deps.sfxUiBlip();
|
||||
return;
|
||||
}
|
||||
|
||||
if (actionIdx === 1) {
|
||||
// Return to draw pile
|
||||
const drawPile = getDrawPile(item);
|
||||
const newDrawPile = [...drawPile, card];
|
||||
const newHands = { ...handsObj, [nickname]: newHand };
|
||||
deps.signalingSend({
|
||||
type: 'item_update',
|
||||
type: 'item_interact',
|
||||
itemId: item.id,
|
||||
params: { draw_pile: newDrawPile, hands: newHands },
|
||||
action: 'return_to_pile',
|
||||
params: { card_index: cardIndex },
|
||||
});
|
||||
deps.state.cardTableHandIndex = Math.min(cardIndex, Math.max(0, newHand.length - 1));
|
||||
if (newHand.length === 0) {
|
||||
deps.state.mode = 'cardTableMenu';
|
||||
deps.state.cardTableMenuIndex = 2;
|
||||
deps.updateStatus(`${cardName(card)} returned to draw pile. Hand is empty.`);
|
||||
} else {
|
||||
deps.state.mode = 'cardTableHand';
|
||||
deps.updateStatus(`${cardName(card)} returned to draw pile.`);
|
||||
}
|
||||
deps.state.mode = 'cardTableHand';
|
||||
deps.updateStatus('Returning card to draw pile.');
|
||||
deps.sfxUiBlip();
|
||||
return;
|
||||
}
|
||||
@@ -395,28 +353,15 @@ export function createCardTableController(deps: CardTableControllerDeps): {
|
||||
|
||||
// Take card from discard into hand
|
||||
const cardIdx = deps.state.cardTableDiscardIndex;
|
||||
const card = discardPile[cardIdx];
|
||||
const newDiscard = [...discardPile];
|
||||
newDiscard.splice(cardIdx, 1);
|
||||
|
||||
const hands = item.params['hands'];
|
||||
const handsObj: Record<string, string[]> =
|
||||
hands && typeof hands === 'object' && !Array.isArray(hands)
|
||||
? (hands as Record<string, string[]>)
|
||||
: {};
|
||||
const currentHand = Array.isArray(handsObj[nickname]) ? [...handsObj[nickname]] : [];
|
||||
currentHand.push(card);
|
||||
const newHands = { ...handsObj, [nickname]: currentHand };
|
||||
|
||||
deps.signalingSend({
|
||||
type: 'item_update',
|
||||
type: 'item_interact',
|
||||
itemId: item.id,
|
||||
params: { discard_pile: newDiscard, hands: newHands },
|
||||
action: 'draw_from_discard',
|
||||
params: { card_index: cardIdx },
|
||||
});
|
||||
|
||||
deps.state.mode = 'cardTableMenu';
|
||||
deps.state.cardTableMenuIndex = 0;
|
||||
deps.updateStatus(`Took ${cardName(card)} from discard pile.`);
|
||||
deps.updateStatus('Taking card from discard pile.');
|
||||
deps.sfxUiBlip();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -141,10 +141,13 @@ export function createWhiteboardController(deps: WhiteboardControllerDeps): {
|
||||
deps.sfxUiBlip();
|
||||
} else {
|
||||
// Delete
|
||||
const newLines = [...lines];
|
||||
newLines.splice(lineIndex, 1);
|
||||
deps.signalingSend({ type: 'item_update', itemId: item.id, params: { lines: newLines } });
|
||||
deps.state.whiteboardLineIndex = Math.min(deps.state.whiteboardLineIndex, newLines.length);
|
||||
deps.signalingSend({
|
||||
type: 'item_interact',
|
||||
itemId: item.id,
|
||||
action: 'delete_line',
|
||||
params: { line_index: lineIndex },
|
||||
});
|
||||
deps.state.whiteboardLineIndex = Math.min(deps.state.whiteboardLineIndex, Math.max(0, lines.length - 1));
|
||||
deps.state.mode = 'whiteboardLines';
|
||||
deps.updateStatus('Line deleted.');
|
||||
deps.sfxUiBlip();
|
||||
@@ -175,20 +178,21 @@ export function createWhiteboardController(deps: WhiteboardControllerDeps): {
|
||||
return;
|
||||
}
|
||||
|
||||
const lines = getLines(item);
|
||||
const editIndex = deps.state.whiteboardEditingLineIndex;
|
||||
let newLines: string[];
|
||||
if (editIndex !== null) {
|
||||
newLines = [...lines];
|
||||
newLines[editIndex] = text;
|
||||
deps.signalingSend({
|
||||
type: 'item_interact',
|
||||
itemId: item.id,
|
||||
action: 'edit_line',
|
||||
params: { line_index: editIndex, text },
|
||||
});
|
||||
} else {
|
||||
newLines = [...lines, text];
|
||||
}
|
||||
|
||||
deps.signalingSend({ type: 'item_update', itemId: item.id, params: { lines: newLines } });
|
||||
|
||||
if (editIndex === null) {
|
||||
deps.state.whiteboardLineIndex = newLines.length - 1;
|
||||
deps.signalingSend({
|
||||
type: 'item_interact',
|
||||
itemId: item.id,
|
||||
action: 'add_line',
|
||||
params: { text },
|
||||
});
|
||||
}
|
||||
|
||||
deps.state.nicknameInput = '';
|
||||
|
||||
@@ -241,7 +241,7 @@ export const itemRemoveSchema = z.object({
|
||||
export const itemActionResultSchema = z.object({
|
||||
type: z.literal('item_action_result'),
|
||||
ok: z.boolean(),
|
||||
action: z.enum(['add', 'pickup', 'drop', 'delete', 'transfer', 'use', 'secondary_use', 'update']),
|
||||
action: z.enum(['add', 'pickup', 'drop', 'delete', 'transfer', 'use', 'secondary_use', 'update', 'interact']),
|
||||
message: z.string(),
|
||||
itemId: z.string().optional(),
|
||||
});
|
||||
@@ -415,6 +415,7 @@ export type OutgoingMessage =
|
||||
| { type: 'item_transfer'; itemId: string; targetUserId: string }
|
||||
| { type: 'item_use'; itemId: string }
|
||||
| { type: 'item_secondary_use'; itemId: string }
|
||||
| { type: 'item_interact'; itemId: string; action: string; params?: Record<string, unknown> }
|
||||
| { type: 'item_piano_note'; itemId: string; keyId: string; midi: number; on: boolean }
|
||||
| { type: 'item_piano_recording'; itemId: string; action: 'toggle_record' | 'playback' | 'stop_playback' | 'stop_record' }
|
||||
| {
|
||||
|
||||
Reference in New Issue
Block a user