Skip to content

Instantly share code, notes, and snippets.

@sergeysova
Created September 18, 2022 20:42
Show Gist options
  • Save sergeysova/14318b49f81c692234f05dd6f786c33c to your computer and use it in GitHub Desktop.
Save sergeysova/14318b49f81c692234f05dd6f786c33c to your computer and use it in GitHub Desktop.
import {
$currentPlayerId,
$gameMode,
$nextPlayerId,
$players,
GameMode,
NO_CURRENT_PLAYER,
Player,
Uuid,
changeGameMode,
common,
gearDecrease,
gearIncrease,
gearReset,
levelDown,
levelUp,
playerJoined,
playerKill,
playerLeft,
playerNameChanged,
playersReordered,
restartGame,
sexChange,
turnNext,
turnSet,
} from '../common';
import { sample, createEffect } from 'effector';
export * from '../common';
export const reportStoreUpdateFx = createEffect<
{ sid: string; name: string; value: unknown },
void
>();
const MAX_LEVEL: { [Key in GameMode]: number } = {
common: 10,
legendary: 20,
unlimited: Infinity,
};
const MIN_LEVEL = 1;
for (const $store of common.history.stores) {
sample({
clock: $store,
fn: (value) => ({ value, sid: $store.sid, name: $store.compositeName.fullName }),
target: reportStoreUpdateFx,
});
}
$gameMode.on(changeGameMode, (_, newMode) => newMode);
$players.on(changeGameMode, (players, gameMode) =>
players.map((player) => ({
...player,
level: Math.min(Math.max(player.level, MIN_LEVEL), MAX_LEVEL[gameMode]),
})),
);
$currentPlayerId.reset(restartGame);
$players.on(restartGame, (players) => players.map((player) => ({ ...player, level: 1, gear: 0 })));
$players
.on(playerJoined, (list, player) => [...list, player])
.on(playersReordered, (players, orderedIds) =>
orderedIds.map((id) => players.find((player) => player.id === id)!),
);
const playerLeftGame = sample({
clock: playerLeft,
source: { current: $currentPlayerId, next: $nextPlayerId, list: $players },
fn: ({ next, current, list }, leftId) => {
let nextId = leftId === current ? next : current;
if (list.length === 1) {
nextId = NO_CURRENT_PLAYER;
}
return {
next: nextId,
list: list.filter((player) => player.id !== leftId),
};
},
});
$players.on(playerLeftGame, (_, { list }) => list);
$currentPlayerId.on(playerLeftGame, (_, { next }) => next);
$players.on(playerNameChanged, (players, { id, name }) =>
players.map((player) => (player.id === id ? { ...player, name } : player)),
);
$currentPlayerId.on(turnSet, (_, playerId) => playerId);
sample({
clock: turnNext,
source: $nextPlayerId,
target: $currentPlayerId,
});
$players
.on(
sexChange,
update((player) => ({ sex: player.sex === 'male' ? 'female' : 'male' })),
)
.on(
gearIncrease,
update((player) => ({ gear: player.gear + 1 })),
)
.on(
gearDecrease,
update((player) => ({ gear: player.gear - 1 })),
)
.on(
gearReset,
update(() => ({ gear: 0 })),
)
.on(
playerKill,
update(() => ({ gear: 0 })),
);
sample({
clock: levelUp,
source: { players: $players, gameMode: $gameMode },
fn: ({ players, gameMode }, playerId) =>
players.map((player) => {
if (player.id === playerId) {
return { ...player, level: Math.min(player.level + 1, MAX_LEVEL[gameMode]) };
}
return player;
}),
target: $players,
});
$players.on(
levelDown,
update((player) => ({ ...player, level: Math.max(player.level - 1, MIN_LEVEL) })),
);
function update(cb: (player: Player) => Partial<Player> | undefined) {
return (list: Player[], id: Uuid) =>
list.map((player) => {
if (player.id === id) {
const updated = cb(player);
if (updated) {
return { ...player, ...updated };
}
return player;
}
return player;
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment