beep
This commit is contained in:
@@ -0,0 +1,275 @@
|
||||
import { useContext } from "react";
|
||||
import {
|
||||
Grid,
|
||||
TextField,
|
||||
MenuItem,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
FormGroup,
|
||||
FormControlLabel,
|
||||
Checkbox,
|
||||
} from "@mui/material";
|
||||
import { MuiColorInput } from "mui-color-input";
|
||||
import {
|
||||
ConwayConfig,
|
||||
GameContext,
|
||||
Preset,
|
||||
RulesetName,
|
||||
} from "../../../../internal";
|
||||
import { presetDisplayNameMap } from "./const";
|
||||
import { ConwayColorProp } from "./types";
|
||||
import { useGameSpecificOptions } from "../hooks";
|
||||
|
||||
const conwayColorProps = [
|
||||
"liveColor",
|
||||
"deadColor",
|
||||
"startingEnvelopeColor",
|
||||
"finalEnvelopeColor",
|
||||
] as ConwayColorProp[];
|
||||
|
||||
const ConwayControls = () => {
|
||||
const { grid } = useContext(GameContext);
|
||||
const { config, handleUpdate } = useGameSpecificOptions<ConwayConfig>(
|
||||
RulesetName.CONWAY
|
||||
);
|
||||
|
||||
const neighborNumbers =
|
||||
grid.config.cellShape === "hex"
|
||||
? [0, 1, 2, 3, 4, 5, 6]
|
||||
: [0, 1, 2, 3, 4, 5, 6, 7, 8];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Grid item xs={12}>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Preset"
|
||||
onChange={(e) => {
|
||||
handleUpdate({ ...config, preset: e.target.value as Preset });
|
||||
}}
|
||||
select
|
||||
value={config.preset}
|
||||
>
|
||||
{Object.keys(Preset).map((preset) => (
|
||||
<MenuItem key={preset} value={Preset[preset]}>
|
||||
{presetDisplayNameMap[Preset[preset]]}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Average % Alive at Start"
|
||||
type="number"
|
||||
onChange={(e) =>
|
||||
handleUpdate({
|
||||
...config,
|
||||
liveStartPercent: parseInt(e.target.value),
|
||||
})
|
||||
}
|
||||
value={config.liveStartPercent}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<FormControl component="fieldset" variant="standard">
|
||||
<FormLabel component="legend">
|
||||
Live Neighbors Required (Survival)
|
||||
</FormLabel>
|
||||
<FormGroup row>
|
||||
{neighborNumbers.map((num) => (
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={config.neighborsNeededToSurvive.includes(num)}
|
||||
onChange={(e) => {
|
||||
let newNeighborsNeededToSurvive = [
|
||||
...config.neighborsNeededToSurvive,
|
||||
];
|
||||
if (e.target.checked) {
|
||||
newNeighborsNeededToSurvive.push(num);
|
||||
} else {
|
||||
newNeighborsNeededToSurvive =
|
||||
newNeighborsNeededToSurvive.filter(
|
||||
(val) => val !== num
|
||||
);
|
||||
}
|
||||
handleUpdate({
|
||||
...config,
|
||||
neighborsNeededToSurvive: newNeighborsNeededToSurvive,
|
||||
});
|
||||
}}
|
||||
name={num.toString()}
|
||||
/>
|
||||
}
|
||||
label={num.toString()}
|
||||
key={`conway-survival-${num}`}
|
||||
/>
|
||||
))}
|
||||
</FormGroup>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<FormControl component="fieldset" variant="standard">
|
||||
<FormLabel component="legend">
|
||||
Live Neighbors Required (Reproduction)
|
||||
</FormLabel>
|
||||
<FormGroup row>
|
||||
{neighborNumbers.map((num) => (
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={config.neighborsNeededToReproduce.includes(num)}
|
||||
onChange={(e) => {
|
||||
let newNeighborsNeededToReproduce = [
|
||||
...config.neighborsNeededToReproduce,
|
||||
];
|
||||
if (e.target.checked) {
|
||||
newNeighborsNeededToReproduce.push(num);
|
||||
} else {
|
||||
newNeighborsNeededToReproduce =
|
||||
newNeighborsNeededToReproduce.filter(
|
||||
(val) => val !== num
|
||||
);
|
||||
}
|
||||
handleUpdate({
|
||||
...config,
|
||||
neighborsNeededToReproduce:
|
||||
newNeighborsNeededToReproduce,
|
||||
});
|
||||
}}
|
||||
name={num.toString()}
|
||||
/>
|
||||
}
|
||||
label={num.toString()}
|
||||
key={`conway-reproduction-${num}`}
|
||||
/>
|
||||
))}
|
||||
</FormGroup>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
<Grid item md={6} xs={12}>
|
||||
<FormGroup row>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={config.showEnvelope}
|
||||
onChange={(e) => {
|
||||
handleUpdate({
|
||||
...config,
|
||||
showEnvelope: e.target.checked,
|
||||
});
|
||||
}}
|
||||
name={"show-envelope-checkbox"}
|
||||
/>
|
||||
}
|
||||
label={"Show Envelope"}
|
||||
/>
|
||||
{config.showEnvelope && (
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={config.showEnvelopeGradient}
|
||||
onChange={(e) => {
|
||||
handleUpdate({
|
||||
...config,
|
||||
showEnvelopeGradient: e.target.checked,
|
||||
});
|
||||
}}
|
||||
name={"envelope-gradient-checkbox"}
|
||||
/>
|
||||
}
|
||||
label={"Envelope Gradient"}
|
||||
/>
|
||||
)}
|
||||
</FormGroup>
|
||||
</Grid>
|
||||
<Grid item md={6} xs={12}>
|
||||
{config.showEnvelope && config.showEnvelopeGradient && (
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Envelope Gradient Steps"
|
||||
type="number"
|
||||
onChange={(e) =>
|
||||
handleUpdate({
|
||||
...config,
|
||||
envelopeGradientSteps: parseInt(e.target.value),
|
||||
})
|
||||
}
|
||||
value={config.envelopeGradientSteps}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid container item xs={12} spacing={2}>
|
||||
{conwayColorProps.map((color: ConwayColorProp) => {
|
||||
if (
|
||||
(!config.showEnvelope && color === "startingEnvelopeColor") ||
|
||||
((!config.showEnvelope || !config.showEnvelopeGradient) &&
|
||||
color === "finalEnvelopeColor")
|
||||
)
|
||||
return null;
|
||||
let label = "Alive Color";
|
||||
if (color === "deadColor") {
|
||||
label = "Dead Color";
|
||||
} else if (color === "startingEnvelopeColor") {
|
||||
label = config.showEnvelopeGradient
|
||||
? "Initial Envelope Color"
|
||||
: "Envelope Color";
|
||||
} else if (color === "finalEnvelopeColor") {
|
||||
label = "Final Envelope Color";
|
||||
}
|
||||
return (
|
||||
<Grid item key={`conway-color-config-${color}`}>
|
||||
<MuiColorInput
|
||||
format="hex"
|
||||
label={label}
|
||||
value={config[color]}
|
||||
onChange={(newColor) =>
|
||||
handleUpdate({
|
||||
...config,
|
||||
[color]: newColor,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
<Grid item md={6} xs={12}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={config.mortalCells}
|
||||
onChange={(e) => {
|
||||
handleUpdate({
|
||||
...config,
|
||||
mortalCells: e.target.checked,
|
||||
});
|
||||
}}
|
||||
name={"mortal-cells-checkbox"}
|
||||
/>
|
||||
}
|
||||
label={"Mortal Cells (Cells Die After X Ticks)"}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item md={6} xs={12}>
|
||||
{config.mortalCells && (
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Cell Lifespan"
|
||||
type="number"
|
||||
onChange={(e) =>
|
||||
handleUpdate({
|
||||
...config,
|
||||
cellLifespan: parseInt(e.target.value),
|
||||
})
|
||||
}
|
||||
value={config.cellLifespan}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConwayControls;
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Preset } from "../../../../internal";
|
||||
|
||||
export const presetDisplayNameMap = {
|
||||
[Preset.DEFAULT]: "Random Distribution",
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
import ConwayControls from "./ConwayControls";
|
||||
|
||||
export { ConwayControls };
|
||||
@@ -0,0 +1,5 @@
|
||||
export type ConwayColorProp =
|
||||
| "liveColor"
|
||||
| "deadColor"
|
||||
| "startingEnvelopeColor"
|
||||
| "finalEnvelopeColor";
|
||||
@@ -0,0 +1,72 @@
|
||||
import { Grid, Typography, Button } from "@mui/material";
|
||||
import {
|
||||
defaultGameOptions,
|
||||
GameContext,
|
||||
RulesetName,
|
||||
} from "../../../internal";
|
||||
import { ConwayControls } from "./ConwayControls";
|
||||
import { PokemonControls } from "./PokemonControls";
|
||||
import { RockPaperScissorsControls } from "./RockPaperScissorsControls";
|
||||
import { MazeControls } from "./MazeControls";
|
||||
import { SnowflakeControls } from "./SnowflakeControls";
|
||||
import { WarControls } from "./WarControls.ts";
|
||||
import { WaterFlowControls } from "./WaterFlowControls";
|
||||
import { useContext, useMemo } from "react";
|
||||
import { ControlsContext } from "../context";
|
||||
|
||||
const GameSpecificControls = () => {
|
||||
const { currentGame } = useContext(GameContext);
|
||||
const { newGameSpecificConfigs, setNewGameSpecificConfigs } =
|
||||
useContext(ControlsContext);
|
||||
|
||||
const Component = useMemo(() => {
|
||||
switch (currentGame) {
|
||||
case RulesetName.CONWAY:
|
||||
return () => <ConwayControls />;
|
||||
case RulesetName.MAZE_GENERATOR:
|
||||
return () => <MazeControls />;
|
||||
case RulesetName.POKEMON:
|
||||
return () => <PokemonControls />;
|
||||
case RulesetName.ROCK_PAPER_SCISSORS:
|
||||
return () => <RockPaperScissorsControls />;
|
||||
case RulesetName.SNOWFLAKE:
|
||||
return () => <SnowflakeControls />;
|
||||
case RulesetName.WAR:
|
||||
return () => <WarControls />;
|
||||
case RulesetName.WATER_FLOW:
|
||||
return () => <WaterFlowControls />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}, [currentGame]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{Component === null ? (
|
||||
<Grid item xs={12}>
|
||||
<Typography>
|
||||
No settings have been developed for this game yet.
|
||||
</Typography>
|
||||
</Grid>
|
||||
) : (
|
||||
<Component />
|
||||
)}
|
||||
{Component !== null && (
|
||||
<Grid item xs={12}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setNewGameSpecificConfigs({
|
||||
...newGameSpecificConfigs,
|
||||
[currentGame]: defaultGameOptions[currentGame],
|
||||
});
|
||||
}}
|
||||
>
|
||||
Reset to Default
|
||||
</Button>
|
||||
</Grid>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default GameSpecificControls;
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Grid } from "@mui/material";
|
||||
import { MuiColorInput } from "mui-color-input";
|
||||
import { MazeConfig, RulesetName } from "../../../../internal";
|
||||
import { MazeColorProp } from "./types";
|
||||
import { useGameSpecificOptions } from "../hooks";
|
||||
|
||||
const mazeColorProps = ["liveColor", "deadColor"] as MazeColorProp[];
|
||||
|
||||
const MazeControls = () => {
|
||||
const { config, handleUpdate } = useGameSpecificOptions<MazeConfig>(
|
||||
RulesetName.MAZE_GENERATOR
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Grid container item xs={12} spacing={2}>
|
||||
{mazeColorProps.map((color: MazeColorProp) => {
|
||||
let label = "Wall Color";
|
||||
if (color === "deadColor") {
|
||||
label = "Background Color";
|
||||
}
|
||||
return (
|
||||
<Grid item key={`maze-color-config-${color}`}>
|
||||
<MuiColorInput
|
||||
format="hex"
|
||||
label={label}
|
||||
value={config[color]}
|
||||
onChange={(newColor) =>
|
||||
handleUpdate({
|
||||
...config,
|
||||
[color]: newColor,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default MazeControls;
|
||||
@@ -0,0 +1,3 @@
|
||||
import MazeControls from "./MazeControls";
|
||||
|
||||
export { MazeControls };
|
||||
@@ -0,0 +1 @@
|
||||
export type MazeColorProp = "liveColor" | "deadColor";
|
||||
@@ -0,0 +1,136 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
Grid,
|
||||
TextField,
|
||||
FormControlLabel,
|
||||
Checkbox,
|
||||
FormGroup,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
MenuItem,
|
||||
} from "@mui/material";
|
||||
import { MuiColorInput } from "mui-color-input";
|
||||
import {
|
||||
PokemonGameConfig,
|
||||
PokemonType,
|
||||
RulesetName,
|
||||
} from "../../../../internal";
|
||||
import { useGameSpecificOptions } from "../hooks";
|
||||
|
||||
const PokemonControls = () => {
|
||||
const { config, handleUpdate } = useGameSpecificOptions<PokemonGameConfig>(
|
||||
RulesetName.POKEMON
|
||||
);
|
||||
const [typeToChangeColor, setTypeToChangeColor] = useState<PokemonType>(
|
||||
PokemonType.BUG
|
||||
);
|
||||
const { allowedTypes, typeColors } = config;
|
||||
const allTypesAllowed =
|
||||
allowedTypes.length === Object.keys(PokemonType).length;
|
||||
return (
|
||||
<>
|
||||
<Grid item xs={12}>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Mutation Odds (1 in X)"
|
||||
type="number"
|
||||
onChange={(e) =>
|
||||
handleUpdate({
|
||||
...config,
|
||||
randomMutationChance: parseInt(e.target.value),
|
||||
})
|
||||
}
|
||||
value={config.randomMutationChance}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid container item xs={12}>
|
||||
<FormControl>
|
||||
<FormLabel>Enable / Disable Pokemon Types</FormLabel>
|
||||
<FormGroup row>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={allTypesAllowed}
|
||||
onChange={() => {
|
||||
let newTypes = Object.keys(PokemonType).map(
|
||||
(key) => PokemonType[key]
|
||||
);
|
||||
handleUpdate({
|
||||
...config,
|
||||
allowedTypes: allTypesAllowed ? [] : newTypes,
|
||||
});
|
||||
}}
|
||||
name={`enable-type-select-all-checkbox`}
|
||||
value={!allTypesAllowed}
|
||||
/>
|
||||
}
|
||||
label={`${allTypesAllowed ? "Deselect" : "Select"} All`}
|
||||
/>
|
||||
{Object.keys(PokemonType).map((key) => {
|
||||
const type = PokemonType[key];
|
||||
return (
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={allowedTypes.includes(type)}
|
||||
onChange={(e) => {
|
||||
let newTypes = [...allowedTypes];
|
||||
if (e.target.checked) {
|
||||
newTypes.push(type);
|
||||
} else {
|
||||
newTypes = newTypes.filter(
|
||||
(newType) => newType !== type
|
||||
);
|
||||
}
|
||||
handleUpdate({
|
||||
...config,
|
||||
allowedTypes: newTypes,
|
||||
});
|
||||
}}
|
||||
name={`enable-type-${type}-checkbox`}
|
||||
value={allowedTypes.includes(type)}
|
||||
/>
|
||||
}
|
||||
key={`pokemon-type-form-${key}`}
|
||||
label={type.toString()}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</FormGroup>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
<Grid item md={6} xs={12}>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Change Color of Type"
|
||||
onChange={(e) => {
|
||||
setTypeToChangeColor(e.target.value as PokemonType);
|
||||
}}
|
||||
select
|
||||
value={typeToChangeColor}
|
||||
>
|
||||
{Object.keys(PokemonType).map((key) => (
|
||||
<MenuItem key={key} value={PokemonType[key]}>
|
||||
{PokemonType[key]}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</Grid>
|
||||
<Grid item md={6} xs={12}>
|
||||
<MuiColorInput
|
||||
format="hex"
|
||||
label={`${typeToChangeColor} Color`}
|
||||
value={typeColors[typeToChangeColor]}
|
||||
onChange={(newColor) =>
|
||||
handleUpdate({
|
||||
...config,
|
||||
typeColors: { ...typeColors, [typeToChangeColor]: newColor },
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PokemonControls;
|
||||
@@ -0,0 +1,3 @@
|
||||
import PokemonControls from "./PokemonControls";
|
||||
|
||||
export { PokemonControls };
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { Grid } from "@mui/material";
|
||||
import { MuiColorInput } from "mui-color-input";
|
||||
import { RPSGameConfig, RulesetName } from "../../../../internal";
|
||||
import { useGameSpecificOptions } from "../hooks";
|
||||
|
||||
const RockPaperScissorsControls = () => {
|
||||
const { config, handleUpdate } = useGameSpecificOptions<RPSGameConfig>(
|
||||
RulesetName.ROCK_PAPER_SCISSORS
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{["rockColor", "paperColor", "scissorsColor"].map(
|
||||
(color: keyof RPSGameConfig, i) => (
|
||||
<Grid item xs={12} key={`rpg-color-config-${color}`}>
|
||||
<MuiColorInput
|
||||
format="hex"
|
||||
label={`Color ${i + 1}`}
|
||||
value={config[color]}
|
||||
onChange={(newColor) =>
|
||||
handleUpdate({
|
||||
...config,
|
||||
[color]: newColor,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default RockPaperScissorsControls;
|
||||
@@ -0,0 +1,3 @@
|
||||
import RockPaperScissorsControls from "./RockPaperScissorsControls";
|
||||
|
||||
export { RockPaperScissorsControls };
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Grid } from "@mui/material";
|
||||
import { MuiColorInput } from "mui-color-input";
|
||||
import { SnowflakeGameConfig, RulesetName } from "../../../../internal";
|
||||
import { SnowflakeColorProp } from "./types";
|
||||
import { useGameSpecificOptions } from "../hooks";
|
||||
|
||||
const mazeColorProps = ["liveColor", "deadColor"] as SnowflakeColorProp[];
|
||||
|
||||
const SnowflakeControls = () => {
|
||||
const { config, handleUpdate } = useGameSpecificOptions<SnowflakeGameConfig>(
|
||||
RulesetName.SNOWFLAKE
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Grid container item xs={12} spacing={2}>
|
||||
{mazeColorProps.map((color: SnowflakeColorProp) => {
|
||||
let label = "Alive Color";
|
||||
if (color === "deadColor") {
|
||||
label = "Dead Color";
|
||||
}
|
||||
return (
|
||||
<Grid item key={`snowflake-color-config-${color}`}>
|
||||
<MuiColorInput
|
||||
format="hex"
|
||||
label={label}
|
||||
value={config[color]}
|
||||
onChange={(newColor) =>
|
||||
handleUpdate({
|
||||
...config,
|
||||
[color]: newColor,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SnowflakeControls;
|
||||
@@ -0,0 +1,3 @@
|
||||
import SnowflakeControls from "./SnowflakeControls";
|
||||
|
||||
export { SnowflakeControls };
|
||||
@@ -0,0 +1 @@
|
||||
export type SnowflakeColorProp = "liveColor" | "deadColor";
|
||||
@@ -0,0 +1,68 @@
|
||||
import { Grid, IconButton, Typography } from "@mui/material";
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import AddIcon from "@mui/icons-material/Add";
|
||||
import { MuiColorInput } from "mui-color-input";
|
||||
import {
|
||||
RulesetName,
|
||||
WarGameConfig,
|
||||
getRandomColor,
|
||||
} from "../../../../internal";
|
||||
import { useState } from "react";
|
||||
import { useGameSpecificOptions } from "../hooks";
|
||||
|
||||
const WarControls = () => {
|
||||
const { config, handleUpdate } = useGameSpecificOptions<WarGameConfig>(
|
||||
RulesetName.WAR
|
||||
);
|
||||
const [newArmyColor, setNewArmyColor] = useState<string>(getRandomColor());
|
||||
const { factionColors } = config;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Grid container item xs={12} spacing={2}>
|
||||
{factionColors.map((color, i) => {
|
||||
return (
|
||||
<Grid item key={`army-${color}`} alignItems="center">
|
||||
<Typography sx={{ color, display: "inline" }}>
|
||||
Army {i + 1}
|
||||
</Typography>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
const newFactions = factionColors.filter(
|
||||
(existingColor) => existingColor !== color
|
||||
);
|
||||
handleUpdate({ factionColors: newFactions });
|
||||
}}
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
<Grid container item xs={12} alignItems="center">
|
||||
<Grid item>
|
||||
<MuiColorInput
|
||||
format="hex"
|
||||
label={"New Army Color"}
|
||||
value={newArmyColor}
|
||||
onChange={(newColor) => setNewArmyColor(newColor)}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
const newFactions = [...factionColors, newArmyColor];
|
||||
handleUpdate({ factionColors: newFactions });
|
||||
setNewArmyColor(getRandomColor());
|
||||
}}
|
||||
>
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default WarControls;
|
||||
@@ -0,0 +1,3 @@
|
||||
import WarControls from "./WarControls";
|
||||
|
||||
export { WarControls };
|
||||
@@ -0,0 +1,182 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
Checkbox,
|
||||
FormControlLabel,
|
||||
Grid,
|
||||
IconButton,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import AddIcon from "@mui/icons-material/Add";
|
||||
import { MuiColorInput } from "mui-color-input";
|
||||
import {
|
||||
RulesetName,
|
||||
WaterFlowGameConfig,
|
||||
getRandomColor,
|
||||
} from "../../../../internal";
|
||||
import { useGameSpecificOptions } from "../hooks";
|
||||
|
||||
const WaterFlowControls = () => {
|
||||
const [newWaterColor, setNewWaterColor] = useState(getRandomColor());
|
||||
const { config, handleUpdate } = useGameSpecificOptions<WaterFlowGameConfig>(
|
||||
RulesetName.WATER_FLOW
|
||||
);
|
||||
const { waterColors } = config;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Grid container item xs={12} spacing={2}>
|
||||
<Grid item>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Average Number of Starting Streams"
|
||||
type="number"
|
||||
onChange={(e) =>
|
||||
handleUpdate({
|
||||
...config,
|
||||
averageStartingWaterCells: parseInt(e.target.value),
|
||||
})
|
||||
}
|
||||
value={config.averageStartingWaterCells}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Branching-Off Chance"
|
||||
type="number"
|
||||
onChange={(e) =>
|
||||
handleUpdate({
|
||||
...config,
|
||||
branchingChance: parseInt(e.target.value),
|
||||
})
|
||||
}
|
||||
value={config.branchingChance}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Rock Health Variation"
|
||||
type="number"
|
||||
onChange={(e) =>
|
||||
handleUpdate({
|
||||
...config,
|
||||
rockHealthVariance: parseInt(e.target.value),
|
||||
})
|
||||
}
|
||||
value={config.rockHealthVariance}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={config.trueRandom}
|
||||
onChange={(e) => {
|
||||
handleUpdate({
|
||||
...config,
|
||||
trueRandom: e.target.checked,
|
||||
});
|
||||
}}
|
||||
name={"true-random-checkbox"}
|
||||
value={config.trueRandom}
|
||||
/>
|
||||
}
|
||||
label={"Random Flow Direction"}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container item xs={12} spacing={2} alignItems="center">
|
||||
<Grid item>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={config.blurBackground}
|
||||
onChange={(e) => {
|
||||
handleUpdate({
|
||||
...config,
|
||||
blurBackground: e.target.checked,
|
||||
});
|
||||
}}
|
||||
name={"blur-background-checkbox"}
|
||||
/>
|
||||
}
|
||||
label={"Blur Background"}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
{config.blurBackground && (
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Blur Amount"
|
||||
type="number"
|
||||
onChange={(e) =>
|
||||
handleUpdate({
|
||||
...config,
|
||||
backgroundBlurAmount: parseInt(e.target.value),
|
||||
})
|
||||
}
|
||||
value={config.backgroundBlurAmount}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container item xs={12} spacing={2}>
|
||||
{waterColors.map((color, i) => {
|
||||
return (
|
||||
<Grid item key={`water-color-${color}`} alignItems="center">
|
||||
<Typography sx={{ color, display: "inline" }}>
|
||||
Color {i + 1}
|
||||
</Typography>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
const newWaterColors = waterColors.filter(
|
||||
(existingColor) => existingColor !== color
|
||||
);
|
||||
handleUpdate({ ...config, waterColors: newWaterColors });
|
||||
}}
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
<Grid container item xs={12} spacing={2} alignItems="center">
|
||||
<Grid item>
|
||||
<MuiColorInput
|
||||
format="hex"
|
||||
label={"New Water Color"}
|
||||
value={newWaterColor}
|
||||
onChange={(newColor) => setNewWaterColor(newColor)}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
const newWaterColors = [...waterColors, newWaterColor];
|
||||
handleUpdate({ ...config, waterColors: newWaterColors });
|
||||
setNewWaterColor(getRandomColor());
|
||||
}}
|
||||
>
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<MuiColorInput
|
||||
format="hex"
|
||||
label={"Rock Color"}
|
||||
value={config.baseBackgroundColor}
|
||||
onChange={(newColor) =>
|
||||
handleUpdate({ ...config, baseBackgroundColor: newColor })
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default WaterFlowControls;
|
||||
@@ -0,0 +1,3 @@
|
||||
import WaterFlowControls from "./WaterFlowControls";
|
||||
|
||||
export { WaterFlowControls };
|
||||
@@ -0,0 +1 @@
|
||||
export { default as useGameSpecificOptions } from "./useGameSpecificOptions";
|
||||
@@ -0,0 +1,25 @@
|
||||
import { useCallback, useContext, useMemo } from "react";
|
||||
import { ControlsContext } from "../../context";
|
||||
import { RulesetName } from "../../../../internal";
|
||||
|
||||
const useGameSpecificOptions = <T>(rulesetName: RulesetName) => {
|
||||
const { newGameSpecificConfigs, setNewGameSpecificConfigs } =
|
||||
useContext(ControlsContext);
|
||||
|
||||
const config = newGameSpecificConfigs[rulesetName] as T;
|
||||
|
||||
const handleUpdate = useCallback(
|
||||
(newConfig: T) => {
|
||||
setNewGameSpecificConfigs({
|
||||
...newGameSpecificConfigs,
|
||||
[rulesetName]: newConfig,
|
||||
});
|
||||
},
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[newGameSpecificConfigs, setNewGameSpecificConfigs]
|
||||
);
|
||||
|
||||
return useMemo(() => ({ config, handleUpdate }), [config, handleUpdate]);
|
||||
};
|
||||
|
||||
export default useGameSpecificOptions;
|
||||
@@ -0,0 +1,4 @@
|
||||
import GameSpecificControls from "./GameSpecificControls";
|
||||
|
||||
export * from "./types";
|
||||
export { GameSpecificControls };
|
||||
@@ -0,0 +1,8 @@
|
||||
import { GameSpecificConfig, RulesetName } from "../../../internal";
|
||||
|
||||
export type UpdateConfigFn = (
|
||||
prop: RulesetName,
|
||||
value: GameSpecificConfig
|
||||
) => void;
|
||||
|
||||
export interface GameSpecificControlsProps {}
|
||||
Reference in New Issue
Block a user