Skip to content

Commit

Permalink
feat: More WIP game configurations
Browse files Browse the repository at this point in the history
fix: Minor visual bug fixes for dropdown icon alignment
  • Loading branch information
colin969 committed Oct 10, 2023
1 parent 64ee874 commit 84e0662
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 22 deletions.
12 changes: 11 additions & 1 deletion src/back/game/GameManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -687,10 +687,20 @@ export async function clearPlaytimeTracking() {

export async function findGameConfigs(gameId: string, registry: Map<string, IGameMiddleware>): Promise<GameConfig[]> {
const gameConfigRepository = AppDataSource.getRepository(RawGameConfig);
return gameConfigRepository.find({ where: { gameId: gameId }})
return gameConfigRepository.find({ where: { gameId: In([gameId, 'template']) }})
.then((rawConfigs) => {
return rawConfigs.map((rc) => {
return loadGameConfig(rc, registry);
});
});
}

export async function deleteGameConfig(id: number) {
const gameConfigRepository = AppDataSource.getRepository(RawGameConfig);
await gameConfigRepository.delete({ id });
const gameRepository = AppDataSource.getRepository(Game);
await gameRepository.update(
{ activeGameConfigId: id },
{ activeGameConfigId: null, activeGameConfigOwner: null }
);
}
17 changes: 16 additions & 1 deletion src/back/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,10 @@ export function registerRequestCallbacks(state: BackState, init: () => Promise<v
}
});

state.socketServer.register(BackIn.DELETE_GAME_CONFIG, async (event, id) => {
await GameManager.deleteGameConfig(id);
});

state.socketServer.register(BackIn.DELETE_GAME, async (event, id) => {
const game = await GameManager.removeGameAndAddApps(id,
path.join(state.config.flashpointPath, state.preferences.dataPacksFolderPath),
Expand Down Expand Up @@ -769,10 +773,21 @@ export function registerRequestCallbacks(state: BackState, init: () => Promise<v
}
const configs = await GameManager.findGameConfigs(game.id, state.registry.middlewares);
const activeConfig = configs.find(c => c.id === game.activeGameConfigId);
// Sort configs with templates at top
return {
game,
activeConfig: activeConfig || null,
configs,
configs: configs.sort((a, b) => {
if (a.gameId === 'template' && b.gameId === 'template') {
return a.name.localeCompare(b.name);
} else if (a.gameId === 'template') {
return -1;
} else if (b.gameId === 'template') {
return 1;
} else {
return a.name.localeCompare(b.name);
}
}),
};
});

Expand Down
49 changes: 39 additions & 10 deletions src/renderer/components/GameConfigDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { FloatingContainer } from './FloatingContainer';
import { InputElement, InputField } from './InputField';
import { OpenIcon } from './OpenIcon';
import { SimpleButton } from './SimpleButton';
import { ConfirmElement } from './ConfirmElement';

const { str } = Coerce;

Expand All @@ -20,6 +21,8 @@ export type GameConfigDialogProps = {
close: () => void;
saveConfig: (config: GameConfig, idx: number) => Promise<void>;
deleteConfig: (idx: number) => Promise<void>;
makeTemplateConfig: (idx: number) => Promise<void>;
duplicateConfig: (idx: number) => Promise<void>;
info: FetchedGameInfo;
}

Expand Down Expand Up @@ -82,6 +85,11 @@ export function GameConfigDialog(props: GameConfigDialogProps) {
<div className='game-config-dialog__config' key={idx}>
<div className='game-config-dialog__config-row'>
<div className='game-config-dialog__config-left'>
{ c.gameId === 'template' && (
<div className='game-config-dialog__config-title-prefix'>
{'(Template)'}
</div>
) }
<div className='game-config-dialog__config-title'>
{c.name}
</div>
Expand Down Expand Up @@ -113,16 +121,37 @@ export function GameConfigDialog(props: GameConfigDialogProps) {
<div className='game-config-dialog__config-left'>
</div>
<div className='game-config-dialog__config-right game-config-dialog__config-buttons'>
<SimpleButton
value='Delete'
onClick={() => {
{ c.gameId !== 'template' && (
<SimpleButton
value='Make Template'
onClick={() => {
props.makeTemplateConfig(idx);
}}/>
)}
<ConfirmElement
message={'Are you sure you want to delete this configuration?'}
onConfirm={() => {
props.deleteConfig(idx);
}}/>
}}
render={({ confirm }) => {
return (
<SimpleButton
onClick={() => { confirm(); }}
value='Delete'/>
);
}} />
{ c.owner === 'local' && (
<SimpleButton
value={'Modify'}
onClick={() => {
openEditor(c, idx);
}} />
)}
<SimpleButton
value={c.owner === 'local' ? 'Modify' : 'Make Local Copy'}
value={'Make Copy'}
onClick={() => {
openEditor(c, idx);
}}/>
props.duplicateConfig(idx);
}} />
</div>
</div>
</div>
Expand Down Expand Up @@ -334,12 +363,12 @@ function GameConfigEditorDialog(props: GameConfigEditorDialogProps) {
</div>
</div>
{nameEditRow}
<div className='game-config-dialog-new-middleware'>
{newMiddlewareRow}
</div>
<div className='game-config-dialog-content simple-scroll'>
{rows}
</div>
<div className='game-config-dialog-footer'>
{newMiddlewareRow}
</div>
</div>
</FloatingContainer>
);
Expand Down
54 changes: 49 additions & 5 deletions src/renderer/components/RightBrowseSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ export class RightBrowseSidebar extends React.Component<RightBrowseSidebarProps,
extra={strings} />;

const gameConfigDropdown = this.props.currentGameInfo ? this.props.currentGameInfo.configs.map((val, idx) => {
const prefix = val.gameId === 'template' ? '(Template) ' : '';
return <label
className='curate-page__right-dropdown-content simple-dropdown-button'
key={idx}
Expand All @@ -242,7 +243,7 @@ export class RightBrowseSidebar extends React.Component<RightBrowseSidebarProps,
}
}}>
<div>
{val.name}
{prefix + val.name}
</div>
</label>;
}): [];
Expand Down Expand Up @@ -285,14 +286,55 @@ export class RightBrowseSidebar extends React.Component<RightBrowseSidebarProps,
if (this.props.currentGameInfo) {
const newInfo = deepCopy(this.props.currentGameInfo);
if (idx > -1 && idx < newInfo.configs.length) {
const removed = newInfo.configs.splice(idx, 1);
if (newInfo.game.activeGameConfigId === removed[0].id) {
const removed = newInfo.configs.splice(idx, 1)[0];
// Templates need to be forcefully removed
if (removed.gameId === 'template') {
await window.Shared.back.request(BackIn.DELETE_GAME_CONFIG, removed.id);
}
if (newInfo.game.activeGameConfigId === removed.id) {
newInfo.activeConfig = null;
}
}
this.props.onForceSaveGame(newInfo);
}
}
};

const duplicateGameConfig = async (idx: number) => {
if (this.props.currentGameInfo) {
const newCopy: GameConfig = {
...this.props.currentGameInfo.configs[idx]
};
// Hack to get a new ID when it next saves
(newCopy as any).id = null;
newCopy.gameId = this.props.currentGameInfo.game.id;
newCopy.name = 'Copy - ' + newCopy.name;
newCopy.owner = 'local';

// Add it to game config list to force the template to save
const newInfo = deepCopy(this.props.currentGameInfo);
newInfo.configs.push(newCopy);
this.props.onForceSaveGame(newInfo);
}
};

const makeTemplateGameConfig = async (idx: number) => {
if (this.props.currentGameInfo) {
const template: GameConfig = {
...this.props.currentGameInfo.configs[idx]
};
// Hack to get a new ID when it next saves
(template as any).id = null;
template.gameId = 'template';

// Add it to game config list to force the template to save
const newInfo = deepCopy(this.props.currentGameInfo);
newInfo.configs.unshift(template);
this.props.onForceSaveGame(newInfo);
}
};

const activeConfig = this.props.currentGameInfo?.activeConfig;
const configNamePrefix = activeConfig && activeConfig.gameId === 'template' ? '(Template) ' : '';

return (
<div
Expand All @@ -303,6 +345,8 @@ export class RightBrowseSidebar extends React.Component<RightBrowseSidebarProps,
<GameConfigDialog
saveConfig={saveGameConfig}
deleteConfig={deleteGameConfig}
makeTemplateConfig={makeTemplateGameConfig}
duplicateConfig={duplicateGameConfig}
info={this.props.currentGameInfo}
close={this.closeGameConfigDialog}
/>
Expand Down Expand Up @@ -916,7 +960,7 @@ export class RightBrowseSidebar extends React.Component<RightBrowseSidebarProps,
</div>
<Dropdown
className={`browse-right-sidebar__game-config-dropdown ${this.props.currentGameInfo?.activeConfig ? '' : 'browse-right-sidebar__game-config-dropdown-none'}`}
text={this.props.currentGameInfo?.activeConfig?.name || 'No Configuration'}>
text={activeConfig ? `${configNamePrefix}${activeConfig.name}` : 'No Configuration'}>
{gameConfigDropdown}
</Dropdown>
<div
Expand Down
4 changes: 2 additions & 2 deletions src/shared/back/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export enum BackIn {
GET_EXEC,
SAVE_GAMES,
SAVE_GAME,
SAVE_GAME_CONFIG,
DELETE_GAME_CONFIG,
GET_GAME,
GET_GAMES_GAME_DATA,
GET_GAME_DATA,
Expand Down Expand Up @@ -263,7 +263,7 @@ export type BackInTemplate = SocketTemplate<BackIn, {
[BackIn.SET_LOCALE]: (data: string) => string;
[BackIn.GET_EXEC]: () => ExecMapping[];
[BackIn.SAVE_GAME]: (data: FetchedGameInfo) => BrowseChangeData;
[BackIn.SAVE_GAME_CONFIG]: (config: GameConfig) => GameConfig;
[BackIn.DELETE_GAME_CONFIG]: (id: number) => void;
[BackIn.SAVE_GAMES]: (data: Game[]) => void;
[BackIn.GET_GAME]: (id: string) => FetchedGameInfo | null;
[BackIn.GET_ALL_GAMES]: (startFrom?: string) => Game[];
Expand Down
29 changes: 26 additions & 3 deletions static/window/styles/core.css
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ body {
}
.simple-dropdown__select-icon {
width: 1.25em;
align-self: center;
flex: 0 0 auto;
margin-top: -0.125em;
}
Expand All @@ -196,7 +197,7 @@ body {
}
.simple-dropdown__content {
z-index: 10;
width: inherit;
width: 100%;
display: block;
position: absolute;
/* Pimp */
Expand Down Expand Up @@ -247,6 +248,7 @@ body {
flex: 0 0 auto;
text-align: center;
font-size: 0.75rem;
align-self: center;
}
.input-dropdown__content {
width: 100%;
Expand Down Expand Up @@ -2830,6 +2832,10 @@ body {
justify-content: space-evenly;
}

.confirm-dialog__buttons > .simple-button {
font-size: 1.4rem;
}

/** Floating Containers */
.floating-container__wrapper {
position: fixed;
Expand Down Expand Up @@ -3263,6 +3269,13 @@ body {
margin-right: 0.5rem;
}

.game-config-dialog__config-title-prefix {
align-self: center;
font-style: italic;
font-size: 1.1em;
margin-right: 1rem;
}

.game-config-dialog__config-version {
align-self: center;
}
Expand Down Expand Up @@ -3295,7 +3308,7 @@ body {

.game-config-dialog-inputs > .game-config-dialog-label-row:not(:first-child) {
border-top: 1px solid;
margin-top: 0.4rem;
padding-top: 0.4rem;
margin-bottom: 0.2rem;
}

Expand All @@ -3307,6 +3320,15 @@ body {
margin-top: 1rem;
}

.game-config-dialog-new-middleware {
margin-bottom: 1rem;
font-size: 1.4em;
}

.game-config-dialog-new-middleware > .game-config-dialog__config-row {
align-items: center;
}

.game-config-dialog-footer {
margin-top: 1rem;
font-size: 1.4em;
Expand Down Expand Up @@ -3360,13 +3382,14 @@ body {
width: 1.25em;
flex: 0 0 auto;
align-self: center;
text-align: center;
}
.simple-dropdown-form__select-icon:before {
content: "▾";
}
.simple-dropdown-form__content {
z-index: 10;
width: inherit;
width: 100%;
display: block;
z-index: 9999;
/* Pimp */
Expand Down

0 comments on commit 84e0662

Please sign in to comment.