@jeremyckahn/farmhand 1.23.2 → 1.23.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/assets/index-4ynbl-GC.js +392 -0
- package/dist/assets/index-4ynbl-GC.js.map +1 -0
- package/dist/assets/index-CaYdR-lC.css +1 -0
- package/dist/assets/jersey-10-latin-400-normal-DrL73VYW.woff2 +0 -0
- package/dist/assets/jersey-10-latin-ext-400-normal-uIKqQSaG.woff2 +0 -0
- package/dist/assets/jersey-20-latin-400-normal-bNi78tgO.woff2 +0 -0
- package/dist/assets/jersey-20-latin-ext-400-normal-BO3lmWef.woff2 +0 -0
- package/dist/assets/jersey-25-latin-400-normal-BuYJnnt7.woff2 +0 -0
- package/dist/assets/jersey-25-latin-ext-400-normal-CP5Jl3WN.woff2 +0 -0
- package/dist/index.html +2 -2
- package/dist/service-worker.js +1 -1
- package/dist/service-worker.js.map +1 -1
- package/package.json +7 -12
- package/src/common/services/randomNumber.test.ts +61 -1
- package/src/common/services/randomNumber.ts +36 -1
- package/src/common/utils.ts +22 -13
- package/src/components/AccountingView/AccountingView.tsx +7 -13
- package/src/components/Achievement/Achievement.tsx +2 -15
- package/src/components/AchievementsView/AchievementsView.tsx +2 -7
- package/src/components/AnimatedNumber/AnimatedNumber.tsx +0 -6
- package/src/components/AppBar/AppBar.tsx +21 -17
- package/src/components/Cellar/Cellar.tsx +0 -2
- package/src/components/Cellar/CellarInventoryTabPanel.tsx +0 -6
- package/src/components/Cellar/FermentationTabPanel.tsx +0 -6
- package/src/components/Cellar/Keg.tsx +0 -5
- package/src/components/Cellar/TabPanel/index.tsx +0 -7
- package/src/components/Cellar/WinemakingTabPanel.tsx +0 -6
- package/src/components/ContextPane/ContextPane.tsx +0 -6
- package/src/components/CowCard/Bloodline/Bloodline.tsx +0 -6
- package/src/components/CowCard/CowCard.tsx +7 -39
- package/src/components/CowCard/Subheader/Subheader.tsx +21 -44
- package/src/components/CowPen/Cow.tsx +5 -11
- package/src/components/CowPen/CowPen.test.tsx +4 -4
- package/src/components/CowPen/CowPen.tsx +5 -16
- package/src/components/CowPenContextMenu/CowPenContextMenu.tsx +2 -18
- package/src/components/CowPenContextMenu/TabPanel/index.tsx +0 -7
- package/src/components/Farmhand/Farmhand.context.tsx +4 -3
- package/src/components/Farmhand/Farmhand.tsx +11 -15
- package/src/components/Farmhand/FarmhandReducers.tsx +1 -2
- package/src/components/Farmhand/FarmhandService.test.ts +6 -9
- package/src/components/Farmhand/hooks/useFarmhandDayAdvancement.ts +2 -6
- package/src/components/Farmhand/hooks/useFarmhandNetwork.test.ts +2 -2
- package/src/components/Farmhand/hooks/useFarmhandNetwork.ts +15 -31
- package/src/components/Farmhand/useFarmhand.test.ts +7 -5
- package/src/components/Farmhand/useFarmhand.ts +24 -15
- package/src/components/FermentationRecipeList/FermentationRecipe.tsx +0 -5
- package/src/components/FermentationRecipeList/FermentationRecipeList.test.tsx +10 -11
- package/src/components/FermentationRecipeList/FermentationRecipeList.tsx +2 -3
- package/src/components/Field/Field.tsx +15 -50
- package/src/components/Forest/Forest.tsx +10 -7
- package/src/components/ForestPlot/ForestPlot.tsx +5 -5
- package/src/components/ForestQuickSelect/ForestQuickSelect.tsx +0 -12
- package/src/components/Home/Home.tsx +2 -7
- package/src/components/Home/SnowBackground.tsx +1 -1
- package/src/components/IngredientsList/IngredientsList.tsx +0 -7
- package/src/components/Inventory/Inventory.test.tsx +4 -4
- package/src/components/Inventory/Inventory.tsx +5 -12
- package/src/components/Item/Item.tsx +11 -29
- package/src/components/ItemList/ItemList.tsx +4 -11
- package/src/components/KeybindingsView/KeybindingsView.tsx +0 -2
- package/src/components/LogView/LogView.tsx +6 -28
- package/src/components/Navigation/DayAndProgressContainer.tsx +0 -8
- package/src/components/Navigation/Navigation.tsx +12 -33
- package/src/components/NotificationSystem/NotificationSystem.test.tsx +45 -3
- package/src/components/NotificationSystem/NotificationSystem.tsx +45 -32
- package/src/components/OnlinePeersView/OnlinePeer/OnlinePeer.test.tsx +2 -2
- package/src/components/OnlinePeersView/OnlinePeer/OnlinePeer.tsx +0 -11
- package/src/components/OnlinePeersView/OnlinePeersView.tsx +0 -10
- package/src/components/PixelIcon/createPixelIcon.test.tsx +59 -0
- package/src/components/PixelIcon/createPixelIcon.tsx +97 -0
- package/src/components/PixelIcon/icons.ts +445 -0
- package/src/components/PixelIcon/index.ts +3 -0
- package/src/components/Plot/Plot.tsx +3 -3
- package/src/components/PriceEventView/PriceEventView.tsx +0 -6
- package/src/components/ProgressBar/ProgressBar.tsx +9 -8
- package/src/components/QuantityInput/QuantityInput.tsx +6 -11
- package/src/components/QuickSelect/QuickSelect.tsx +0 -10
- package/src/components/Recipe/Recipe.tsx +0 -9
- package/src/components/RecipeList/RecipeList.tsx +0 -6
- package/src/components/SearchBar/SearchBar.tsx +4 -10
- package/src/components/SettingsView/RandomSeedInput.test.tsx +2 -4
- package/src/components/SettingsView/RandomSeedInput.tsx +5 -8
- package/src/components/SettingsView/SettingsView.test.tsx +21 -0
- package/src/components/SettingsView/SettingsView.tsx +24 -18
- package/src/components/Shop/Shop.tsx +0 -20
- package/src/components/Shop/TabPanel/index.tsx +0 -7
- package/src/components/Stage/Stage.tsx +11 -20
- package/src/components/StatsView/StatsView.tsx +0 -18
- package/src/components/TierPurchase/TierPurchase.tsx +0 -12
- package/src/components/Toolbelt/Toolbelt.tsx +5 -10
- package/src/components/UpdateNotifier/UpdateNotifier.tsx +33 -5
- package/src/components/UpgradePurchase/UpgradePurchase.tsx +0 -10
- package/src/components/WineRecipeList/WineRecipe.test.tsx +2 -2
- package/src/components/WineRecipeList/WineRecipe.tsx +0 -5
- package/src/components/WineRecipeList/WineRecipeList.tsx +2 -3
- package/src/components/Workshop/ForgeTabPanel.tsx +0 -8
- package/src/components/Workshop/KitchenTabPanel.tsx +0 -7
- package/src/components/Workshop/RecyclingTabPanel.tsx +0 -7
- package/src/components/Workshop/TabPanel/index.tsx +0 -7
- package/src/components/Workshop/WoodChipperTabPanel.tsx +0 -7
- package/src/components/Workshop/Workshop.tsx +0 -9
- package/src/components/Workshop/getUpgradesAvailable.ts +1 -1
- package/src/constants.ts +18 -13
- package/src/data/crops/grape.ts +13 -15
- package/src/data/maps.test.ts +3 -4
- package/src/data/maps.ts +27 -29
- package/src/enums.ts +47 -19
- package/src/factories/OreFactory.ts +2 -1
- package/src/farmhand.d.ts +6 -3
- package/src/game-logic/reducers/applyPrecipitation.ts +4 -4
- package/src/game-logic/reducers/generatePriceEvents.ts +6 -3
- package/src/game-logic/reducers/harvestForestPlot.ts +1 -2
- package/src/game-logic/reducers/makeFermentationRecipe.ts +2 -3
- package/src/game-logic/reducers/minePlot.test.ts +2 -2
- package/src/game-logic/reducers/minePlot.ts +1 -1
- package/src/game-logic/reducers/processCowFertilizerProduction.test.ts +16 -14
- package/src/game-logic/reducers/processFeedingCows.test.ts +2 -5
- package/src/game-logic/reducers/purchaseCow.ts +2 -7
- package/src/game-logic/reducers/showNotification.test.ts +20 -0
- package/src/game-logic/reducers/showNotification.ts +4 -2
- package/src/game-logic/reducers/updateAchievements.ts +1 -1
- package/src/game-logic/reducers/updateFinancialRecords.test.ts +21 -25
- package/src/game-logic/reducers/updateFinancialRecords.ts +2 -5
- package/src/game-logic/reducers/updateInventoryRecordsForNextDay.test.ts +12 -14
- package/src/handlers/ui-events.test.ts +44 -42
- package/src/handlers/ui-events.tsx +18 -3
- package/src/hooks/usePrefersReducedMotion.ts +10 -6
- package/src/index.tsx +0 -2
- package/src/mui-theme.ts +258 -37
- package/src/scripts/generate-crop-table.ts +3 -2
- package/src/setupTests.ts +18 -12
- package/src/strings.ts +1 -1
- package/src/styles/fonts.ts +73 -0
- package/src/styles/pixel.ts +151 -0
- package/src/styles/sx.ts +46 -33
- package/src/styles/tokens.ts +11 -0
- package/src/test-utils/index.ts +1 -0
- package/src/utils/chooseRandom.ts +4 -1
- package/src/utils/chooseRandomIndex.ts +6 -2
- package/src/utils/getCowImage.ts +22 -27
- package/src/utils/getMaxYieldOfFermentationRecipe.ts +2 -2
- package/src/utils/getPeerMetadata.ts +1 -1
- package/src/utils/getPlotImage.test.ts +14 -14
- package/src/utils/getPlotImage.ts +10 -10
- package/src/utils/getRandomUnlockedCrop.ts +5 -3
- package/src/utils/getRandomizedLifespan.test.ts +2 -8
- package/src/utils/getValueAdjustmentStream.test.ts +9 -0
- package/src/utils/getValueAdjustmentStream.ts +5 -0
- package/src/utils/isItemAFarmProduct.ts +2 -2
- package/src/utils/shouldPrecipitateToday.ts +3 -1
- package/src/utils/shouldStormToday.ts +2 -1
- package/src/utils/transformStateDataForImport.ts +3 -5
- package/dist/assets/francois-one-latin-400-normal-DD1rFI7H.woff2 +0 -0
- package/dist/assets/francois-one-latin-400-normal-DNXs7uOx.woff +0 -0
- package/dist/assets/francois-one-latin-ext-400-normal-CwRdWRZD.woff2 +0 -0
- package/dist/assets/francois-one-latin-ext-400-normal-JvkpT0Av.woff +0 -0
- package/dist/assets/francois-one-vietnamese-400-normal-BLIKeG5Y.woff2 +0 -0
- package/dist/assets/francois-one-vietnamese-400-normal-CuWeHlXs.woff +0 -0
- package/dist/assets/index-CNcrTYN-.css +0 -1
- package/dist/assets/index-DNPchtK9.js +0 -844
- package/dist/assets/index-DNPchtK9.js.map +0 -1
- package/dist/assets/public-sans-latin-400-normal-8Rpg0ruU.woff2 +0 -0
- package/dist/assets/public-sans-latin-400-normal-SBbinRkI.woff +0 -0
- package/dist/assets/public-sans-latin-ext-400-normal-B02wwOdZ.woff +0 -0
- package/dist/assets/public-sans-latin-ext-400-normal-mk90oQqJ.woff2 +0 -0
- package/dist/assets/public-sans-vietnamese-400-normal-BO1meqcx.woff +0 -0
- package/dist/assets/public-sans-vietnamese-400-normal-TxZB8OSn.woff2 +0 -0
- package/src/fontsource.d.ts +0 -3
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from 'react'
|
|
2
2
|
|
|
3
|
-
import { faMars, faVenus } from '@fortawesome/free-solid-svg-icons'
|
|
4
|
-
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
5
3
|
import Button from '@mui/material/Button/index.js'
|
|
6
4
|
import Card from '@mui/material/Card/index.js'
|
|
7
5
|
import CardActions from '@mui/material/CardActions/index.js'
|
|
@@ -10,7 +8,6 @@ import TextField from '@mui/material/TextField/index.js'
|
|
|
10
8
|
import Tooltip from '@mui/material/Tooltip/index.js'
|
|
11
9
|
import Typography from '@mui/material/Typography/index.js'
|
|
12
10
|
import classNames from 'classnames'
|
|
13
|
-
import { array, bool, func, number, object, string } from 'prop-types'
|
|
14
11
|
import { useIsMounted } from 'usehooks-ts'
|
|
15
12
|
|
|
16
13
|
import { PURCHASEABLE_COW_PENS } from '../../constants.js'
|
|
@@ -29,13 +26,14 @@ import { isCowInBreedingPen } from '../../utils/isCowInBreedingPen.js'
|
|
|
29
26
|
import { isInViewport } from '../../utils/isInViewport.js'
|
|
30
27
|
import { A } from '../Elements/index.js'
|
|
31
28
|
import FarmhandContext, { BoundHandlers } from '../Farmhand/Farmhand.context.js'
|
|
29
|
+
import { FemaleIcon, MaleIcon } from '../PixelIcon/index.js'
|
|
32
30
|
|
|
33
31
|
import Subheader from './Subheader/index.js'
|
|
34
32
|
|
|
35
33
|
const genderIcons = {
|
|
36
|
-
[genders.FEMALE as string]:
|
|
37
|
-
[genders.MALE as string]:
|
|
38
|
-
} as Record<string, typeof
|
|
34
|
+
[genders.FEMALE as string]: FemaleIcon,
|
|
35
|
+
[genders.MALE as string]: MaleIcon,
|
|
36
|
+
} as Record<string, typeof FemaleIcon>
|
|
39
37
|
|
|
40
38
|
export interface CowCardProps {
|
|
41
39
|
allowCustomPeerCowNames: farmhand.state['allowCustomPeerCowNames']
|
|
@@ -157,6 +155,8 @@ export const CowCard = ({
|
|
|
157
155
|
}
|
|
158
156
|
}, [isSelected])
|
|
159
157
|
|
|
158
|
+
const GenderIcon = genderIcons[cow.gender]
|
|
159
|
+
|
|
160
160
|
return (
|
|
161
161
|
<>
|
|
162
162
|
<A
|
|
@@ -233,11 +233,7 @@ export const CowCard = ({
|
|
|
233
233
|
) : (
|
|
234
234
|
displayName
|
|
235
235
|
)}{' '}
|
|
236
|
-
<
|
|
237
|
-
{...{
|
|
238
|
-
icon: genderIcons[cow.gender],
|
|
239
|
-
}}
|
|
240
|
-
/>
|
|
236
|
+
<GenderIcon fontSize="inherit" />
|
|
241
237
|
</>
|
|
242
238
|
),
|
|
243
239
|
subheader: (
|
|
@@ -279,7 +275,6 @@ export const CowCard = ({
|
|
|
279
275
|
{canCowBeTradedFor && (
|
|
280
276
|
<Tooltip
|
|
281
277
|
{...{
|
|
282
|
-
arrow: true,
|
|
283
278
|
placement: 'top',
|
|
284
279
|
title: 'The game will be saved when the trade is completed.',
|
|
285
280
|
}}
|
|
@@ -312,7 +307,6 @@ export const CowCard = ({
|
|
|
312
307
|
(cowIdOfferedForTrade === cow.id ? (
|
|
313
308
|
<Tooltip
|
|
314
309
|
{...{
|
|
315
|
-
arrow: true,
|
|
316
310
|
placement: 'top',
|
|
317
311
|
title: WITHDRAW_COW_FROM_TRADE('', cowDisplayName),
|
|
318
312
|
}}
|
|
@@ -333,7 +327,6 @@ export const CowCard = ({
|
|
|
333
327
|
) : (
|
|
334
328
|
<Tooltip
|
|
335
329
|
{...{
|
|
336
|
-
arrow: true,
|
|
337
330
|
placement: 'top',
|
|
338
331
|
title: (
|
|
339
332
|
<Typography>
|
|
@@ -374,31 +367,6 @@ export const CowCard = ({
|
|
|
374
367
|
)
|
|
375
368
|
}
|
|
376
369
|
|
|
377
|
-
CowCard.propTypes = {
|
|
378
|
-
allowCustomPeerCowNames: bool.isRequired,
|
|
379
|
-
cow: object.isRequired,
|
|
380
|
-
cowBreedingPen: object.isRequired,
|
|
381
|
-
cowIdOfferedForTrade: string.isRequired,
|
|
382
|
-
cowInventory: array.isRequired,
|
|
383
|
-
debounced: object,
|
|
384
|
-
handleCowAutomaticHugChange: func,
|
|
385
|
-
handleCowBreedChange: func,
|
|
386
|
-
handleCowHugClick: func,
|
|
387
|
-
handleCowNameInputChange: func,
|
|
388
|
-
handleCowOfferClick: func,
|
|
389
|
-
handleCowPurchaseClick: func,
|
|
390
|
-
handleCowWithdrawClick: func,
|
|
391
|
-
handleCowSellClick: func,
|
|
392
|
-
handleCowTradeClick: func,
|
|
393
|
-
playerId: string.isRequired,
|
|
394
|
-
inventory: array.isRequired,
|
|
395
|
-
isCowOfferedForTradeByPeer: bool,
|
|
396
|
-
isOnline: bool.isRequired,
|
|
397
|
-
isSelected: bool,
|
|
398
|
-
money: number.isRequired,
|
|
399
|
-
purchasedCowPen: number.isRequired,
|
|
400
|
-
}
|
|
401
|
-
|
|
402
370
|
export default function Consumer(
|
|
403
371
|
props: Pick<CowCardProps, 'cow' | 'isCowOfferedForTradeByPeer' | 'isSelected'>
|
|
404
372
|
) {
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import { faHeart as faEmptyHeart } from '@fortawesome/free-regular-svg-icons'
|
|
2
|
-
import { faHeart as faFullHeart } from '@fortawesome/free-solid-svg-icons'
|
|
3
|
-
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
4
1
|
import Checkbox from '@mui/material/Checkbox/index.js'
|
|
5
2
|
import FormControlLabel from '@mui/material/FormControlLabel/index.js'
|
|
6
3
|
import Tooltip from '@mui/material/Tooltip/index.js'
|
|
7
4
|
import Typography from '@mui/material/Typography/index.js'
|
|
8
5
|
import classNames from 'classnames'
|
|
9
|
-
import { array, bool, func, object, string } from 'prop-types'
|
|
10
6
|
|
|
11
7
|
import { huggingMachine } from '../../../data/items.js'
|
|
12
8
|
import { genders } from '../../../enums.js'
|
|
@@ -19,6 +15,7 @@ import { isCowInBreedingPen } from '../../../utils/isCowInBreedingPen.js'
|
|
|
19
15
|
import { memoize } from '../../../utils/memoize.js'
|
|
20
16
|
import { moneyString } from '../../../utils/moneyString.js'
|
|
21
17
|
import { nullArray } from '../../../utils/nullArray.js'
|
|
18
|
+
import { HeartIcon, HeartOutlineIcon } from '../../PixelIcon/index.js'
|
|
22
19
|
import Bloodline from '../Bloodline/index.js'
|
|
23
20
|
import { CowCardProps } from '../CowCard.js'
|
|
24
21
|
|
|
@@ -37,18 +34,17 @@ const getCowMapById = memoize((cowInventory: farmhand.state['cowInventory']) =>
|
|
|
37
34
|
)
|
|
38
35
|
)
|
|
39
36
|
|
|
40
|
-
export interface SubheaderProps
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
> {
|
|
37
|
+
export interface SubheaderProps extends Pick<
|
|
38
|
+
CowCardProps,
|
|
39
|
+
| 'cow'
|
|
40
|
+
| 'cowBreedingPen'
|
|
41
|
+
| 'cowIdOfferedForTrade'
|
|
42
|
+
| 'cowInventory'
|
|
43
|
+
| 'handleCowAutomaticHugChange'
|
|
44
|
+
| 'handleCowBreedChange'
|
|
45
|
+
| 'huggingMachinesRemain'
|
|
46
|
+
| 'playerId'
|
|
47
|
+
> {
|
|
52
48
|
canCowBeTradedFor: boolean
|
|
53
49
|
cowValue: number
|
|
54
50
|
isCowPurchased: boolean
|
|
@@ -116,25 +112,20 @@ const Subheader = ({
|
|
|
116
112
|
<ol className="hearts">
|
|
117
113
|
{nullArray(10).map((_null: null, i: number) => (
|
|
118
114
|
<li key={`${cow.id}_${i}`}>
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
'is-full': isHeartFull(i, numberOfFullHearts),
|
|
129
|
-
}),
|
|
130
|
-
}}
|
|
131
|
-
/>
|
|
115
|
+
{isHeartFull(i, numberOfFullHearts) ? (
|
|
116
|
+
<HeartIcon
|
|
117
|
+
className="heart is-full"
|
|
118
|
+
fontSize="inherit"
|
|
119
|
+
htmlColor={colors.heart}
|
|
120
|
+
/>
|
|
121
|
+
) : (
|
|
122
|
+
<HeartOutlineIcon className="heart" fontSize="inherit" />
|
|
123
|
+
)}
|
|
132
124
|
</li>
|
|
133
125
|
))}
|
|
134
126
|
</ol>
|
|
135
127
|
<Tooltip
|
|
136
128
|
{...{
|
|
137
|
-
arrow: true,
|
|
138
129
|
placement: 'top',
|
|
139
130
|
title: (
|
|
140
131
|
<Typography>
|
|
@@ -165,7 +156,6 @@ const Subheader = ({
|
|
|
165
156
|
</Tooltip>
|
|
166
157
|
<Tooltip
|
|
167
158
|
{...{
|
|
168
|
-
arrow: true,
|
|
169
159
|
placement: 'top',
|
|
170
160
|
disableFocusListener: disableBreedingControlTooltip,
|
|
171
161
|
disableHoverListener: disableBreedingControlTooltip,
|
|
@@ -210,16 +200,3 @@ const Subheader = ({
|
|
|
210
200
|
}
|
|
211
201
|
|
|
212
202
|
export default Subheader
|
|
213
|
-
|
|
214
|
-
Subheader.propTypes = {
|
|
215
|
-
canCowBeTradedFor: bool.isRequired,
|
|
216
|
-
cow: object.isRequired,
|
|
217
|
-
cowBreedingPen: object.isRequired,
|
|
218
|
-
cowIdOfferedForTrade: string.isRequired,
|
|
219
|
-
cowInventory: array.isRequired,
|
|
220
|
-
handleCowAutomaticHugChange: func,
|
|
221
|
-
handleCowBreedChange: func,
|
|
222
|
-
huggingMachinesRemain: bool.isRequired,
|
|
223
|
-
playerId: string.isRequired,
|
|
224
|
-
isCowPurchased: bool,
|
|
225
|
-
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { faHeart } from '@fortawesome/free-solid-svg-icons'
|
|
2
|
-
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
3
1
|
import Tooltip from '@mui/material/Tooltip/index.js'
|
|
4
2
|
import Typography from '@mui/material/Typography/index.js'
|
|
5
3
|
import classNames from 'classnames'
|
|
@@ -12,6 +10,7 @@ import { LEFT, RIGHT } from '../../constants.js'
|
|
|
12
10
|
import { pixel } from '../../img/index.js'
|
|
13
11
|
import { getCowDisplayName } from '../../utils/getCowDisplayName.js'
|
|
14
12
|
import { getCowImage } from '../../utils/getCowImage.js'
|
|
13
|
+
import { HeartIcon } from '../PixelIcon/index.js'
|
|
15
14
|
|
|
16
15
|
// Only moves the cow within the middle 80% of the pen
|
|
17
16
|
const randomPosition = () => 10 + random() * 80
|
|
@@ -249,7 +248,6 @@ export const Cow = ({
|
|
|
249
248
|
)}
|
|
250
249
|
<Tooltip
|
|
251
250
|
{...{
|
|
252
|
-
arrow: true,
|
|
253
251
|
placement: 'top',
|
|
254
252
|
title: <Typography>{cowDisplayName}</Typography>,
|
|
255
253
|
open: isSelected,
|
|
@@ -265,12 +263,12 @@ export const Cow = ({
|
|
|
265
263
|
}}
|
|
266
264
|
alt={cowDisplayName}
|
|
267
265
|
/>
|
|
268
|
-
<
|
|
266
|
+
<HeartIcon
|
|
269
267
|
{...{
|
|
270
|
-
className: classNames('animation', {
|
|
268
|
+
className: classNames('heart-icon', 'animation', {
|
|
271
269
|
'is-animating': showHugAnimation,
|
|
272
270
|
}),
|
|
273
|
-
|
|
271
|
+
fontSize: 'inherit',
|
|
274
272
|
}}
|
|
275
273
|
/>
|
|
276
274
|
</div>
|
|
@@ -278,11 +276,7 @@ export const Cow = ({
|
|
|
278
276
|
<ol {...{ className: 'happiness-boosts-today' }}>
|
|
279
277
|
{new Array(cow.happinessBoostsToday).fill(undefined).map((_, i) => (
|
|
280
278
|
<li {...{ key: i }}>
|
|
281
|
-
<
|
|
282
|
-
{...{
|
|
283
|
-
icon: faHeart,
|
|
284
|
-
}}
|
|
285
|
-
/>
|
|
279
|
+
<HeartIcon className="heart-icon" fontSize="inherit" />
|
|
286
280
|
</li>
|
|
287
281
|
))}
|
|
288
282
|
</ol>
|
|
@@ -94,7 +94,7 @@ describe('Cow', () => {
|
|
|
94
94
|
|
|
95
95
|
render(<Cow {...defaultCowProps} cow={happyCow} />)
|
|
96
96
|
|
|
97
|
-
expect(document.querySelector('.
|
|
97
|
+
expect(document.querySelector('.heart-icon')).toBeInTheDocument()
|
|
98
98
|
})
|
|
99
99
|
|
|
100
100
|
test('does not show happiness indicator when cow is not happy', () => {
|
|
@@ -214,7 +214,7 @@ describe('Cow', () => {
|
|
|
214
214
|
/>
|
|
215
215
|
)
|
|
216
216
|
|
|
217
|
-
const heart = () => container.querySelector('.
|
|
217
|
+
const heart = () => container.querySelector('.heart-icon.animation')
|
|
218
218
|
|
|
219
219
|
rerender(
|
|
220
220
|
<Cow
|
|
@@ -234,7 +234,7 @@ describe('Cow', () => {
|
|
|
234
234
|
/>
|
|
235
235
|
)
|
|
236
236
|
|
|
237
|
-
const heart = () => container.querySelector('.
|
|
237
|
+
const heart = () => container.querySelector('.heart-icon.animation')
|
|
238
238
|
|
|
239
239
|
rerender(
|
|
240
240
|
<Cow
|
|
@@ -258,7 +258,7 @@ describe('Cow', () => {
|
|
|
258
258
|
/>
|
|
259
259
|
)
|
|
260
260
|
|
|
261
|
-
const heart = () => container.querySelector('.
|
|
261
|
+
const heart = () => container.querySelector('.heart-icon.animation')
|
|
262
262
|
|
|
263
263
|
// Midnight: the daily reset brings the boost count back down.
|
|
264
264
|
rerender(
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Theme } from '@mui/material/styles/index.js'
|
|
2
|
-
import { array, bool, func, string } from 'prop-types'
|
|
3
2
|
import { useEffect } from 'react'
|
|
4
3
|
|
|
5
4
|
import { fillSx } from '../../styles/sx.js'
|
|
@@ -10,11 +9,10 @@ import FarmhandContext from '../Farmhand/Farmhand.context.js'
|
|
|
10
9
|
import { Cow } from './Cow.js'
|
|
11
10
|
import { Tumbleweeds } from './Tumbleweeds.js'
|
|
12
11
|
|
|
13
|
-
export interface CowPenProps
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
> {
|
|
12
|
+
export interface CowPenProps extends Pick<
|
|
13
|
+
farmhand.state,
|
|
14
|
+
'allowCustomPeerCowNames' | 'cowInventory' | 'playerId' | 'selectedCowId'
|
|
15
|
+
> {
|
|
18
16
|
handleCowPenUnmount: () => void
|
|
19
17
|
handleCowClick: (cow: farmhand.cow) => void
|
|
20
18
|
}
|
|
@@ -72,7 +70,7 @@ export const CowPen = ({
|
|
|
72
70
|
easing: theme.transitions.easing.easeOut,
|
|
73
71
|
}),
|
|
74
72
|
},
|
|
75
|
-
'& .
|
|
73
|
+
'& .heart-icon': {
|
|
76
74
|
color: colors.heart,
|
|
77
75
|
'&.animation': {
|
|
78
76
|
opacity: 0,
|
|
@@ -170,15 +168,6 @@ export const CowPen = ({
|
|
|
170
168
|
)
|
|
171
169
|
}
|
|
172
170
|
|
|
173
|
-
CowPen.propTypes = {
|
|
174
|
-
allowCustomPeerCowNames: bool.isRequired,
|
|
175
|
-
cowInventory: array.isRequired,
|
|
176
|
-
handleCowClick: func.isRequired,
|
|
177
|
-
handleCowPenUnmount: func.isRequired,
|
|
178
|
-
playerId: string.isRequired,
|
|
179
|
-
selectedCowId: string.isRequired,
|
|
180
|
-
}
|
|
181
|
-
|
|
182
171
|
export default function Consumer(props: Partial<CowPenProps>) {
|
|
183
172
|
return (
|
|
184
173
|
<FarmhandContext.Consumer>
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward.js'
|
|
2
|
-
import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward.js'
|
|
3
1
|
import Fab from '@mui/material/Fab/index.js'
|
|
4
2
|
import MenuItem from '@mui/material/MenuItem/index.js'
|
|
5
3
|
import Select from '@mui/material/Select/index.js'
|
|
6
4
|
import Tab from '@mui/material/Tab/index.js'
|
|
7
5
|
import Tabs from '@mui/material/Tabs/index.js'
|
|
8
6
|
import sortBy from 'lodash.sortby'
|
|
9
|
-
import { array, func, number, object, string } from 'prop-types'
|
|
10
7
|
import { useEffect, useState } from 'react'
|
|
11
8
|
|
|
9
|
+
import { ArrowDownwardIcon, ArrowUpwardIcon } from '../PixelIcon/index.js'
|
|
10
|
+
|
|
12
11
|
import { PURCHASEABLE_COW_PENS } from '../../constants.js'
|
|
13
12
|
import cowShopInventory from '../../data/shop-inventory-cow.js'
|
|
14
13
|
import uiEventHandlers from '../../handlers/ui-events.js'
|
|
@@ -327,21 +326,6 @@ export const CowPenContextMenu = ({
|
|
|
327
326
|
)
|
|
328
327
|
}
|
|
329
328
|
|
|
330
|
-
CowPenContextMenu.propTypes = {
|
|
331
|
-
cowForSale: object.isRequired,
|
|
332
|
-
cowInventory: array.isRequired,
|
|
333
|
-
handleCowAutomaticHugChange: func.isRequired,
|
|
334
|
-
handleCowBreedChange: func.isRequired,
|
|
335
|
-
handleCowHugClick: func.isRequired,
|
|
336
|
-
handleCowNameInputChange: func.isRequired,
|
|
337
|
-
handleCowOfferClick: func.isRequired,
|
|
338
|
-
handleCowSelect: func.isRequired,
|
|
339
|
-
handleCowSellClick: func.isRequired,
|
|
340
|
-
handleCowWithdrawClick: func.isRequired,
|
|
341
|
-
purchasedCowPen: number.isRequired,
|
|
342
|
-
selectedCowId: string.isRequired,
|
|
343
|
-
}
|
|
344
|
-
|
|
345
329
|
export default function Consumer() {
|
|
346
330
|
return (
|
|
347
331
|
<FarmhandContext.Consumer>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { node, number } from 'prop-types'
|
|
3
2
|
|
|
4
3
|
export const TabPanel = (
|
|
5
4
|
props: React.PropsWithChildren<
|
|
@@ -21,12 +20,6 @@ export const TabPanel = (
|
|
|
21
20
|
)
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
TabPanel.propTypes = {
|
|
25
|
-
children: node,
|
|
26
|
-
index: number.isRequired,
|
|
27
|
-
value: number.isRequired,
|
|
28
|
-
}
|
|
29
|
-
|
|
30
23
|
export const a11yProps = (index: number) => ({
|
|
31
24
|
id: `cow-context-tab-${index}`,
|
|
32
25
|
'aria-controls': `cow-context-tabpanel-${index}`,
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import uiEventHandlers from '../../handlers/ui-events.js'
|
|
13
13
|
import { generateCow } from '../../utils/generateCow.js'
|
|
14
14
|
import { scarecrow } from '../../data/items.js'
|
|
15
|
+
import { NOTIFICATION_DURATION_DEFAULT } from '../../constants.js'
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* A utility type that transforms a type containing functions with an explicit `this` parameter
|
|
@@ -159,6 +160,7 @@ export const createContextData = (): ContextData => {
|
|
|
159
160
|
latestNotification: null,
|
|
160
161
|
newDayNotifications: [],
|
|
161
162
|
notificationLog: [],
|
|
163
|
+
notificationDuration: NOTIFICATION_DURATION_DEFAULT,
|
|
162
164
|
peers: {}, // empty object for now
|
|
163
165
|
peerRoom: null,
|
|
164
166
|
pendingPeerMessages: [],
|
|
@@ -217,8 +219,7 @@ export const createContextData = (): ContextData => {
|
|
|
217
219
|
}
|
|
218
220
|
}
|
|
219
221
|
|
|
220
|
-
const FarmhandContext: import('react').Context<ContextData> =
|
|
221
|
-
ContextData
|
|
222
|
-
>(createContextData())
|
|
222
|
+
const FarmhandContext: import('react').Context<ContextData> =
|
|
223
|
+
createContext<ContextData>(createContextData())
|
|
223
224
|
|
|
224
225
|
export default FarmhandContext
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import HotelIcon from '@mui/icons-material/Hotel.js'
|
|
2
|
-
import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft.js'
|
|
3
|
-
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight.js'
|
|
4
|
-
import MenuIcon from '@mui/icons-material/Menu.js'
|
|
5
1
|
import CssBaseline from '@mui/material/CssBaseline/index.js'
|
|
6
2
|
import Drawer from '@mui/material/Drawer/index.js'
|
|
7
3
|
import Fab from '@mui/material/Fab/index.js'
|
|
@@ -11,10 +7,16 @@ import Tooltip from '@mui/material/Tooltip/index.js'
|
|
|
11
7
|
import classNames from 'classnames'
|
|
12
8
|
import localforage from 'localforage'
|
|
13
9
|
import { SnackbarProvider } from 'notistack'
|
|
14
|
-
import { object } from 'prop-types'
|
|
15
10
|
import { GlobalHotKeys } from 'react-hotkeys'
|
|
16
11
|
import { Redirect } from 'react-router-dom'
|
|
17
12
|
|
|
13
|
+
import {
|
|
14
|
+
HotelIcon,
|
|
15
|
+
KeyboardArrowLeftIcon as KeyboardArrowLeft,
|
|
16
|
+
KeyboardArrowRightIcon as KeyboardArrowRight,
|
|
17
|
+
MenuIcon,
|
|
18
|
+
} from '../PixelIcon/index.js'
|
|
19
|
+
|
|
18
20
|
import { Z_INDEX } from '../../constants.js'
|
|
19
21
|
import theme, { blueStripeBg } from '../../mui-theme.js'
|
|
20
22
|
import { Div } from '../Elements/index.js'
|
|
@@ -103,9 +105,10 @@ const Farmhand = (props: FarmhandProps) => {
|
|
|
103
105
|
pointerEvents: 'none',
|
|
104
106
|
},
|
|
105
107
|
}),
|
|
106
|
-
[`@media (min-width: ${breakpoints.smallPhone}px) and (orientation: landscape)`]:
|
|
107
|
-
|
|
108
|
-
|
|
108
|
+
[`@media (min-width: ${breakpoints.smallPhone}px) and (orientation: landscape)`]:
|
|
109
|
+
{
|
|
110
|
+
paddingTop: '3em',
|
|
111
|
+
},
|
|
109
112
|
[`@media (min-width: ${breakpoints.sm}px)`]: {
|
|
110
113
|
paddingTop: '4em',
|
|
111
114
|
},
|
|
@@ -282,11 +285,4 @@ Farmhand.defaultProps = {
|
|
|
282
285
|
match: { path: '', params: {} },
|
|
283
286
|
}
|
|
284
287
|
|
|
285
|
-
Farmhand.propTypes = {
|
|
286
|
-
features: object,
|
|
287
|
-
history: object,
|
|
288
|
-
location: object,
|
|
289
|
-
match: object.isRequired,
|
|
290
|
-
}
|
|
291
|
-
|
|
292
288
|
export default Farmhand
|
|
@@ -193,8 +193,7 @@ export class FarmhandReducers extends Component<FarmhandProps, FarmhandState> {
|
|
|
193
193
|
|
|
194
194
|
for (const reducerName of reducerNames) {
|
|
195
195
|
const reducer = reducers[reducerName as keyof typeof reducers] as
|
|
196
|
-
|
|
197
|
-
| undefined
|
|
196
|
+
((state: farmhand.state, ...args: any[]) => farmhand.state) | undefined
|
|
198
197
|
|
|
199
198
|
if (!reducer) {
|
|
200
199
|
if (import.meta.env?.MODE === 'development') {
|
|
@@ -50,9 +50,8 @@ describe('FarmhandService', () => {
|
|
|
50
50
|
{ id: 'carrot-seed', quantity: 1 },
|
|
51
51
|
{ id: 'weed', quantity: 1 },
|
|
52
52
|
]
|
|
53
|
-
const plantableCropInventory =
|
|
54
|
-
inventory
|
|
55
|
-
)
|
|
53
|
+
const plantableCropInventory =
|
|
54
|
+
FarmhandService.getPlantableCropInventory(inventory)
|
|
56
55
|
|
|
57
56
|
expect(plantableCropInventory).toEqual([{ ...carrotSeed, quantity: 1 }])
|
|
58
57
|
})
|
|
@@ -64,9 +63,8 @@ describe('FarmhandService', () => {
|
|
|
64
63
|
{ id: 'apple-sapling', quantity: 1 },
|
|
65
64
|
{ id: 'weed', quantity: 1 },
|
|
66
65
|
]
|
|
67
|
-
const plantableTreeInventory =
|
|
68
|
-
inventory
|
|
69
|
-
)
|
|
66
|
+
const plantableTreeInventory =
|
|
67
|
+
FarmhandService.getPlantableTreeInventory(inventory)
|
|
70
68
|
|
|
71
69
|
expect(plantableTreeInventory).toEqual([{ ...appleSapling, quantity: 1 }])
|
|
72
70
|
})
|
|
@@ -76,9 +74,8 @@ describe('FarmhandService', () => {
|
|
|
76
74
|
{ id: 'apple-sapling', quantity: 1 },
|
|
77
75
|
{ id: 'not-a-real-item-id', quantity: 1 },
|
|
78
76
|
]
|
|
79
|
-
const plantableTreeInventory =
|
|
80
|
-
inventory
|
|
81
|
-
)
|
|
77
|
+
const plantableTreeInventory =
|
|
78
|
+
FarmhandService.getPlantableTreeInventory(inventory)
|
|
82
79
|
|
|
83
80
|
expect(plantableTreeInventory).toEqual([{ ...appleSapling, quantity: 1 }])
|
|
84
81
|
})
|
|
@@ -50,12 +50,8 @@ export const useFarmhandDayAdvancement = (
|
|
|
50
50
|
let serverValueAdjustments: Record<string, number> | undefined
|
|
51
51
|
|
|
52
52
|
if (stateRef.current.isOnline) {
|
|
53
|
-
const {
|
|
54
|
-
|
|
55
|
-
room,
|
|
56
|
-
todaysPurchases,
|
|
57
|
-
todaysStartingInventory,
|
|
58
|
-
} = stateRef.current
|
|
53
|
+
const { inventory, room, todaysPurchases, todaysStartingInventory } =
|
|
54
|
+
stateRef.current
|
|
59
55
|
|
|
60
56
|
const positions = computeMarketPositions(
|
|
61
57
|
todaysStartingInventory,
|
|
@@ -58,14 +58,14 @@ const setup = () => {
|
|
|
58
58
|
const sendCowTradeRequest = vitest.fn()
|
|
59
59
|
const showNotification = vitest.fn()
|
|
60
60
|
|
|
61
|
-
const fakeState =
|
|
61
|
+
const fakeState = {
|
|
62
62
|
peers: {
|
|
63
63
|
[peerId]: { playerId: ownerId } as farmhand.peerMetadata,
|
|
64
64
|
},
|
|
65
65
|
sendCowTradeRequest,
|
|
66
66
|
cowInventory: [cowOfferedForTrade],
|
|
67
67
|
cowIdOfferedForTrade: cowOfferedForTrade.id,
|
|
68
|
-
} as unknown
|
|
68
|
+
} as unknown as farmhand.state
|
|
69
69
|
|
|
70
70
|
const instanceProxyRef: React.MutableRefObject<any> = {
|
|
71
71
|
current: { state: { ...fakeState } },
|
|
@@ -83,12 +83,8 @@ export const useFarmhandNetwork = (
|
|
|
83
83
|
const tradeForPeerCow = useCallback(
|
|
84
84
|
(peerPlayerCow: farmhand.cow) => {
|
|
85
85
|
const latestState = instanceProxyRef.current?.state ?? state
|
|
86
|
-
const {
|
|
87
|
-
|
|
88
|
-
cowInventory,
|
|
89
|
-
peers,
|
|
90
|
-
sendCowTradeRequest,
|
|
91
|
-
} = latestState
|
|
86
|
+
const { cowIdOfferedForTrade, cowInventory, peers, sendCowTradeRequest } =
|
|
87
|
+
latestState
|
|
92
88
|
|
|
93
89
|
if (!sendCowTradeRequest) return
|
|
94
90
|
|
|
@@ -139,7 +135,7 @@ export const useFarmhandNetwork = (
|
|
|
139
135
|
|
|
140
136
|
setState(previous => ({
|
|
141
137
|
...previous,
|
|
142
|
-
cowTradeTimeoutId:
|
|
138
|
+
cowTradeTimeoutId: cowTradeTimeoutId as unknown as number,
|
|
143
139
|
isAwaitingCowTradeRequest: true,
|
|
144
140
|
}))
|
|
145
141
|
},
|
|
@@ -153,26 +149,20 @@ export const useFarmhandNetwork = (
|
|
|
153
149
|
return previous
|
|
154
150
|
})
|
|
155
151
|
|
|
156
|
-
const timeoutId =
|
|
152
|
+
const timeoutId = window.setTimeout(() => {
|
|
157
153
|
setState((previous: farmhand.state) => ({
|
|
158
154
|
...previous,
|
|
159
155
|
money: moneyTotal(previous.money, previous.activePlayers ?? 0),
|
|
160
156
|
}))
|
|
161
157
|
scheduleHeartbeat()
|
|
162
|
-
}, HEARTBEAT_INTERVAL_PERIOD) as unknown
|
|
158
|
+
}, HEARTBEAT_INTERVAL_PERIOD) as unknown as number
|
|
163
159
|
|
|
164
160
|
setState(previous => ({ ...previous, heartbeatTimeoutId: timeoutId }))
|
|
165
161
|
}, [setState])
|
|
166
162
|
|
|
167
163
|
const syncToRoom = useCallback(async () => {
|
|
168
|
-
const {
|
|
169
|
-
|
|
170
|
-
priceCrashes,
|
|
171
|
-
priceSurges,
|
|
172
|
-
room,
|
|
173
|
-
playerId,
|
|
174
|
-
peerRoom,
|
|
175
|
-
} = instanceProxyRef.current.state
|
|
164
|
+
const { isOnline, priceCrashes, priceSurges, room, playerId, peerRoom } =
|
|
165
|
+
instanceProxyRef.current.state
|
|
176
166
|
|
|
177
167
|
if (!isOnline) return
|
|
178
168
|
|
|
@@ -308,27 +298,22 @@ export const useFarmhandNetwork = (
|
|
|
308
298
|
boundReducersRef.current.removePeer(id)
|
|
309
299
|
)
|
|
310
300
|
|
|
311
|
-
const [
|
|
312
|
-
|
|
313
|
-
getPeerMetadataFunc,
|
|
314
|
-
] = statePeerRoom.makeAction('peerMetadata')
|
|
301
|
+
const [sendPeerMetadata, getPeerMetadataFunc] =
|
|
302
|
+
statePeerRoom.makeAction('peerMetadata')
|
|
315
303
|
|
|
316
304
|
getPeerMetadataFunc((...args: any[]) =>
|
|
317
305
|
handlePeerMetadataRequest(instanceProxyRef.current, args[0], args[1])
|
|
318
306
|
)
|
|
319
307
|
|
|
320
|
-
const [
|
|
321
|
-
|
|
322
|
-
getCowTradeRequest,
|
|
323
|
-
] = statePeerRoom.makeAction('cowTrade')
|
|
308
|
+
const [sendCowTradeRequest, getCowTradeRequest] =
|
|
309
|
+
statePeerRoom.makeAction('cowTrade')
|
|
324
310
|
|
|
325
311
|
getCowTradeRequest((...args: any[]) =>
|
|
326
312
|
handleCowTradeRequest(instanceProxyRef.current, args[0], args[1])
|
|
327
313
|
)
|
|
328
314
|
|
|
329
|
-
const [sendCowAccept, getCowAccept] =
|
|
330
|
-
'cowAccept'
|
|
331
|
-
)
|
|
315
|
+
const [sendCowAccept, getCowAccept] =
|
|
316
|
+
statePeerRoom.makeAction('cowAccept')
|
|
332
317
|
|
|
333
318
|
getCowAccept((...args: any[]) =>
|
|
334
319
|
handleCowTradeRequestAccept(
|
|
@@ -338,9 +323,8 @@ export const useFarmhandNetwork = (
|
|
|
338
323
|
)
|
|
339
324
|
)
|
|
340
325
|
|
|
341
|
-
const [sendCowReject, getCowReject] =
|
|
342
|
-
'cowReject'
|
|
343
|
-
)
|
|
326
|
+
const [sendCowReject, getCowReject] =
|
|
327
|
+
statePeerRoom.makeAction('cowReject')
|
|
344
328
|
|
|
345
329
|
getCowReject((...args: any[]) =>
|
|
346
330
|
handleCowTradeRequestReject(instanceProxyRef.current, args[0])
|