Open-source interactive fiction engine, powered by React, Redux and TypeScript. _ https://discoteque.pub/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

53 lines
1.7 KiB

import React from 'react';
import * as R from 'ramda';
import { Engine } from '../engine/Engine';
import styles from '../components/Playback.styles';
import { ILine, ILineOption, Chrono, ILocation, EngineConfig } from '../engine/types';
import { useSelector, useDispatch } from 'react-redux';
import { setState, stateSelector } from '../engine/lib/store';
type PlaybackRenderFn<GS = any, MT = undefined, ST extends string = string> = (
engine: Engine<GS, MT, ST>,
engineConfig: EngineConfig<GS, MT, ST>,
backlog: ILine<GS, MT>[],
location: ILocation<GS, MT> | null,
time: Chrono | null,
next: (opt?: ILineOption<GS>) => void,
) => React.ReactNode;
interface PlaybackProps<GS = any, MT = undefined, ST extends string = string> {
engine: Engine<GS, MT, ST>;
children: PlaybackRenderFn<GS, MT, ST>;
engineConfig: EngineConfig<GS, MT, ST>;
}
const restart = () => location.reload();
const Playback = <GS, MT, ST extends string, >({ engine, children, engineConfig }: PlaybackProps<GS, MT, ST>) => {
const dispatch = useDispatch();
const state = useSelector(stateSelector) as any;
const next = (opt?: ILineOption<GS>) => {
if (!state.isOver) {
const nextLine = engine.next(state as any, opt)
if (nextLine) {
const backlog = engine.backlog;
dispatch(setState({ backlog: [...backlog, ...nextLine].filter(R.identity) }))
}
}
};
return state ? (
<div className={styles.playbackContainer}>
{children(
engine, engineConfig, engine.backlog, engine.currentLocation as any,
engine.currentTime, next,
)}
{state.isOver && <span onClick={restart} className={styles.playbackRestart}>Restart</span>}
</div>
) : <div>Something went wrong :^\(</div>;
}
export default Playback