@jeremyckahn/farmhand 1.23.2 → 1.23.3

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.
Files changed (131) hide show
  1. package/README.md +1 -0
  2. package/dist/assets/{index-DNPchtK9.js → index-Dihg7UqQ.js} +15 -15
  3. package/dist/assets/{index-DNPchtK9.js.map → index-Dihg7UqQ.js.map} +1 -1
  4. package/dist/index.html +1 -1
  5. package/dist/service-worker.js +1 -1
  6. package/dist/service-worker.js.map +1 -1
  7. package/package.json +4 -5
  8. package/src/common/services/randomNumber.test.ts +61 -1
  9. package/src/common/services/randomNumber.ts +36 -1
  10. package/src/common/utils.ts +22 -13
  11. package/src/components/AccountingView/AccountingView.tsx +4 -12
  12. package/src/components/Achievement/Achievement.tsx +0 -13
  13. package/src/components/AchievementsView/AchievementsView.tsx +2 -7
  14. package/src/components/AnimatedNumber/AnimatedNumber.tsx +0 -6
  15. package/src/components/AppBar/AppBar.tsx +0 -10
  16. package/src/components/Cellar/Cellar.tsx +0 -2
  17. package/src/components/Cellar/CellarInventoryTabPanel.tsx +0 -6
  18. package/src/components/Cellar/FermentationTabPanel.tsx +0 -6
  19. package/src/components/Cellar/Keg.tsx +0 -5
  20. package/src/components/Cellar/TabPanel/index.tsx +0 -7
  21. package/src/components/Cellar/WinemakingTabPanel.tsx +0 -6
  22. package/src/components/ContextPane/ContextPane.tsx +0 -6
  23. package/src/components/CowCard/Bloodline/Bloodline.tsx +0 -5
  24. package/src/components/CowCard/CowCard.tsx +0 -26
  25. package/src/components/CowCard/Subheader/Subheader.tsx +11 -26
  26. package/src/components/CowPen/CowPen.tsx +4 -15
  27. package/src/components/CowPenContextMenu/CowPenContextMenu.tsx +0 -16
  28. package/src/components/CowPenContextMenu/TabPanel/index.tsx +0 -7
  29. package/src/components/Farmhand/Farmhand.context.tsx +4 -3
  30. package/src/components/Farmhand/Farmhand.tsx +4 -11
  31. package/src/components/Farmhand/FarmhandReducers.tsx +1 -2
  32. package/src/components/Farmhand/FarmhandService.test.ts +6 -9
  33. package/src/components/Farmhand/hooks/useFarmhandDayAdvancement.ts +2 -6
  34. package/src/components/Farmhand/hooks/useFarmhandNetwork.test.ts +2 -2
  35. package/src/components/Farmhand/hooks/useFarmhandNetwork.ts +15 -31
  36. package/src/components/Farmhand/useFarmhand.test.ts +7 -5
  37. package/src/components/Farmhand/useFarmhand.ts +12 -13
  38. package/src/components/FermentationRecipeList/FermentationRecipe.tsx +0 -5
  39. package/src/components/FermentationRecipeList/FermentationRecipeList.test.tsx +10 -11
  40. package/src/components/FermentationRecipeList/FermentationRecipeList.tsx +2 -3
  41. package/src/components/Field/Field.tsx +13 -48
  42. package/src/components/Forest/Forest.tsx +10 -7
  43. package/src/components/ForestPlot/ForestPlot.tsx +5 -5
  44. package/src/components/ForestQuickSelect/ForestQuickSelect.tsx +0 -12
  45. package/src/components/Home/Home.tsx +0 -6
  46. package/src/components/Home/SnowBackground.tsx +1 -1
  47. package/src/components/IngredientsList/IngredientsList.tsx +0 -7
  48. package/src/components/Inventory/Inventory.test.tsx +4 -4
  49. package/src/components/Inventory/Inventory.tsx +3 -11
  50. package/src/components/Item/Item.tsx +0 -21
  51. package/src/components/ItemList/ItemList.tsx +4 -11
  52. package/src/components/KeybindingsView/KeybindingsView.tsx +0 -2
  53. package/src/components/LogView/LogView.tsx +0 -6
  54. package/src/components/Navigation/DayAndProgressContainer.tsx +0 -7
  55. package/src/components/Navigation/Navigation.tsx +0 -23
  56. package/src/components/NotificationSystem/NotificationSystem.test.tsx +4 -1
  57. package/src/components/NotificationSystem/NotificationSystem.tsx +5 -12
  58. package/src/components/OnlinePeersView/OnlinePeer/OnlinePeer.test.tsx +2 -2
  59. package/src/components/OnlinePeersView/OnlinePeer/OnlinePeer.tsx +0 -11
  60. package/src/components/OnlinePeersView/OnlinePeersView.tsx +0 -10
  61. package/src/components/Plot/Plot.tsx +3 -3
  62. package/src/components/PriceEventView/PriceEventView.tsx +0 -6
  63. package/src/components/ProgressBar/ProgressBar.tsx +0 -5
  64. package/src/components/QuantityInput/QuantityInput.tsx +0 -9
  65. package/src/components/QuickSelect/QuickSelect.tsx +0 -10
  66. package/src/components/Recipe/Recipe.tsx +0 -9
  67. package/src/components/RecipeList/RecipeList.tsx +0 -6
  68. package/src/components/SearchBar/SearchBar.tsx +0 -6
  69. package/src/components/SettingsView/RandomSeedInput.test.tsx +2 -4
  70. package/src/components/SettingsView/RandomSeedInput.tsx +5 -8
  71. package/src/components/SettingsView/SettingsView.test.tsx +21 -0
  72. package/src/components/SettingsView/SettingsView.tsx +24 -16
  73. package/src/components/Shop/Shop.tsx +0 -20
  74. package/src/components/Shop/TabPanel/index.tsx +0 -7
  75. package/src/components/Stage/Stage.tsx +11 -20
  76. package/src/components/StatsView/StatsView.tsx +0 -15
  77. package/src/components/TierPurchase/TierPurchase.tsx +0 -12
  78. package/src/components/Toolbelt/Toolbelt.tsx +5 -10
  79. package/src/components/UpgradePurchase/UpgradePurchase.tsx +0 -10
  80. package/src/components/WineRecipeList/WineRecipe.test.tsx +2 -2
  81. package/src/components/WineRecipeList/WineRecipe.tsx +0 -5
  82. package/src/components/WineRecipeList/WineRecipeList.tsx +2 -3
  83. package/src/components/Workshop/ForgeTabPanel.tsx +0 -8
  84. package/src/components/Workshop/KitchenTabPanel.tsx +0 -7
  85. package/src/components/Workshop/RecyclingTabPanel.tsx +0 -7
  86. package/src/components/Workshop/TabPanel/index.tsx +0 -7
  87. package/src/components/Workshop/WoodChipperTabPanel.tsx +0 -7
  88. package/src/components/Workshop/Workshop.tsx +0 -9
  89. package/src/components/Workshop/getUpgradesAvailable.ts +1 -1
  90. package/src/constants.ts +18 -13
  91. package/src/data/crops/grape.ts +13 -15
  92. package/src/data/maps.test.ts +3 -4
  93. package/src/data/maps.ts +27 -29
  94. package/src/enums.ts +47 -19
  95. package/src/factories/OreFactory.ts +2 -1
  96. package/src/farmhand.d.ts +2 -3
  97. package/src/game-logic/reducers/applyPrecipitation.ts +4 -4
  98. package/src/game-logic/reducers/generatePriceEvents.ts +6 -3
  99. package/src/game-logic/reducers/harvestForestPlot.ts +1 -2
  100. package/src/game-logic/reducers/makeFermentationRecipe.ts +2 -3
  101. package/src/game-logic/reducers/minePlot.test.ts +2 -2
  102. package/src/game-logic/reducers/minePlot.ts +1 -1
  103. package/src/game-logic/reducers/processCowFertilizerProduction.test.ts +16 -14
  104. package/src/game-logic/reducers/processFeedingCows.test.ts +2 -5
  105. package/src/game-logic/reducers/purchaseCow.ts +2 -7
  106. package/src/game-logic/reducers/updateAchievements.ts +1 -1
  107. package/src/game-logic/reducers/updateFinancialRecords.test.ts +21 -25
  108. package/src/game-logic/reducers/updateFinancialRecords.ts +2 -5
  109. package/src/game-logic/reducers/updateInventoryRecordsForNextDay.test.ts +12 -14
  110. package/src/handlers/ui-events.test.ts +44 -42
  111. package/src/handlers/ui-events.tsx +10 -0
  112. package/src/hooks/usePrefersReducedMotion.ts +10 -6
  113. package/src/mui-theme.ts +4 -3
  114. package/src/scripts/generate-crop-table.ts +3 -2
  115. package/src/styles/sx.ts +29 -25
  116. package/src/test-utils/index.ts +1 -0
  117. package/src/utils/chooseRandom.ts +4 -1
  118. package/src/utils/chooseRandomIndex.ts +6 -2
  119. package/src/utils/getCowImage.ts +22 -16
  120. package/src/utils/getMaxYieldOfFermentationRecipe.ts +2 -2
  121. package/src/utils/getPeerMetadata.ts +1 -1
  122. package/src/utils/getPlotImage.test.ts +14 -14
  123. package/src/utils/getPlotImage.ts +10 -10
  124. package/src/utils/getRandomUnlockedCrop.ts +5 -3
  125. package/src/utils/getRandomizedLifespan.test.ts +2 -8
  126. package/src/utils/getValueAdjustmentStream.test.ts +9 -0
  127. package/src/utils/getValueAdjustmentStream.ts +5 -0
  128. package/src/utils/isItemAFarmProduct.ts +2 -2
  129. package/src/utils/shouldPrecipitateToday.ts +3 -1
  130. package/src/utils/shouldStormToday.ts +2 -1
  131. package/src/utils/transformStateDataForImport.ts +3 -5
@@ -6,7 +6,6 @@ import Select from '@mui/material/Select/index.js'
6
6
  import Tab from '@mui/material/Tab/index.js'
7
7
  import Tabs from '@mui/material/Tabs/index.js'
8
8
  import sortBy from 'lodash.sortby'
9
- import { array, func, number, object, string } from 'prop-types'
10
9
  import { useEffect, useState } from 'react'
11
10
 
12
11
  import { PURCHASEABLE_COW_PENS } from '../../constants.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> = createContext<
221
- ContextData
222
- >(createContextData())
222
+ const FarmhandContext: import('react').Context<ContextData> =
223
+ createContext<ContextData>(createContextData())
223
224
 
224
225
  export default FarmhandContext
@@ -11,7 +11,6 @@ import Tooltip from '@mui/material/Tooltip/index.js'
11
11
  import classNames from 'classnames'
12
12
  import localforage from 'localforage'
13
13
  import { SnackbarProvider } from 'notistack'
14
- import { object } from 'prop-types'
15
14
  import { GlobalHotKeys } from 'react-hotkeys'
16
15
  import { Redirect } from 'react-router-dom'
17
16
 
@@ -103,9 +102,10 @@ const Farmhand = (props: FarmhandProps) => {
103
102
  pointerEvents: 'none',
104
103
  },
105
104
  }),
106
- [`@media (min-width: ${breakpoints.smallPhone}px) and (orientation: landscape)`]: {
107
- paddingTop: '3em',
108
- },
105
+ [`@media (min-width: ${breakpoints.smallPhone}px) and (orientation: landscape)`]:
106
+ {
107
+ paddingTop: '3em',
108
+ },
109
109
  [`@media (min-width: ${breakpoints.sm}px)`]: {
110
110
  paddingTop: '4em',
111
111
  },
@@ -282,11 +282,4 @@ Farmhand.defaultProps = {
282
282
  match: { path: '', params: {} },
283
283
  }
284
284
 
285
- Farmhand.propTypes = {
286
- features: object,
287
- history: object,
288
- location: object,
289
- match: object.isRequired,
290
- }
291
-
292
285
  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
- | ((state: farmhand.state, ...args: any[]) => farmhand.state)
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 = FarmhandService.getPlantableCropInventory(
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 = FarmhandService.getPlantableTreeInventory(
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 = FarmhandService.getPlantableTreeInventory(
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
- inventory,
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) as farmhand.state
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
- cowIdOfferedForTrade,
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: (cowTradeTimeoutId as unknown) as number,
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 = (window.setTimeout(() => {
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) as number
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
- isOnline,
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
- sendPeerMetadata,
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
- sendCowTradeRequest,
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] = statePeerRoom.makeAction(
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] = statePeerRoom.makeAction(
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])
@@ -21,13 +21,15 @@ const setWindowHeight = (height: number) => {
21
21
  }
22
22
 
23
23
  const getIsMenuOpen = () =>
24
- ((window as unknown) as { farmhand: { state: farmhand.state } }).farmhand
25
- .state.isMenuOpen
24
+ (window as unknown as { farmhand: { state: farmhand.state } }).farmhand.state
25
+ .isMenuOpen
26
26
 
27
27
  const setIsMenuOpen = (isMenuOpen: boolean) =>
28
- ((window as unknown) as {
29
- farmhand: { setState: (state: Partial<farmhand.state>) => void }
30
- }).farmhand.setState({ isMenuOpen })
28
+ (
29
+ window as unknown as {
30
+ farmhand: { setState: (state: Partial<farmhand.state>) => void }
31
+ }
32
+ ).farmhand.setState({ isMenuOpen })
31
33
 
32
34
  // Simulates a sidebar input having focus, e.g. mid-typing, without depending
33
35
  // on any particular Farmhand-rendered input existing in the current view.
@@ -5,10 +5,12 @@ import { v4 as uuid } from 'uuid'
5
5
 
6
6
  import * as reducers from '../../game-logic/reducers/index.js'
7
7
  import eventHandlers from '../../handlers/ui-events.js'
8
+ import { randomNumberService } from '../../common/services/randomNumber.js'
8
9
 
9
10
  import {
10
11
  DEFAULT_ROOM,
11
12
  INITIAL_STORAGE_LIMIT,
13
+ NOTIFICATION_DURATION_DEFAULT,
12
14
  STAGE_TITLE_MAP,
13
15
  STANDARD_LOAN_AMOUNT,
14
16
  } from '../../constants.js'
@@ -16,6 +18,7 @@ import { scarecrow } from '../../data/items.js'
16
18
  import {
17
19
  dialogView,
18
20
  fieldMode,
21
+ randomStream,
19
22
  stageFocusType,
20
23
  toolLevel,
21
24
  toolType,
@@ -125,6 +128,7 @@ export const useFarmhand = (props: FarmhandProps) => {
125
128
  latestNotification: null,
126
129
  newDayNotifications: [],
127
130
  notificationLog: [],
131
+ notificationDuration: NOTIFICATION_DURATION_DEFAULT,
128
132
  peers: {},
129
133
  peerRoom: null,
130
134
  pendingPeerMessages: [],
@@ -252,12 +256,8 @@ export const useFarmhand = (props: FarmhandProps) => {
252
256
  const instanceProxyRef = useRef<any>(null)
253
257
 
254
258
  // Call sub-hooks
255
- const {
256
- openDialogView,
257
- closeDialogView,
258
- focusNextView,
259
- focusPreviousView,
260
- } = useFarmhandNavigation(setState, viewList)
259
+ const { openDialogView, closeDialogView, focusNextView, focusPreviousView } =
260
+ useFarmhandNavigation(setState, viewList)
261
261
 
262
262
  // Mirrors the current view into the URL hash's `view` query param, using
263
263
  // pushState (not replaceState) so each in-app view change is a real,
@@ -351,15 +351,15 @@ export const useFarmhand = (props: FarmhandProps) => {
351
351
  nextDayStateRef
352
352
  )
353
353
 
354
- const {
355
- showInventoryFullNotifications,
356
- showRecipeLearnedNotifications,
357
- } = useFarmhandNotifications(state, boundReducersRef)
354
+ const { showInventoryFullNotifications, showRecipeLearnedNotifications } =
355
+ useFarmhandNotifications(state, boundReducersRef)
358
356
 
359
357
  // Instance proxy to mimic the legacy class "this" so ui-events.tsx can run unmodified
360
358
  // eslint-disable-next-line react-hooks/exhaustive-deps
361
359
  const instanceProxy = useMemo(
362
360
  () => ({
361
+ queueRandomNumbers: (stream: randomStream, numbers: number[]) =>
362
+ randomNumberService.queueRandomNumbers(stream, numbers),
363
363
  state,
364
364
  props,
365
365
  viewTitle,
@@ -582,9 +582,8 @@ export const useFarmhand = (props: FarmhandProps) => {
582
582
  ...persistedState,
583
583
  })
584
584
  const { isCombineEnabled, newDayNotifications } = sanitizedState
585
- const restoredStageFocus = getValidatedStageFocusFromHash(
586
- sanitizedState
587
- )
585
+ const restoredStageFocus =
586
+ getValidatedStageFocusFromHash(sanitizedState)
588
587
 
589
588
  setState(previous => ({
590
589
  ...previous,
@@ -1,5 +1,4 @@
1
1
  import React, { useContext, useEffect, useState } from 'react'
2
- import { object } from 'prop-types'
3
2
  import Card from '@mui/material/Card/index.js'
4
3
  import CardHeader from '@mui/material/CardHeader/index.js'
5
4
  import CardActions from '@mui/material/CardActions/index.js'
@@ -141,7 +140,3 @@ export const FermentationRecipe = ({ item }: { item: farmhand.item }) => {
141
140
  </Card>
142
141
  )
143
142
  }
144
-
145
- FermentationRecipe.propTypes = {
146
- item: object.isRequired,
147
- }
@@ -30,7 +30,8 @@ const FermentationRecipeListStub = ({
30
30
  } = {}) => {
31
31
  const contextValue = createContextData()
32
32
 
33
- contextValue.gameState.levelEntitlements = levelEntitlements as farmhand.levelEntitlements
33
+ contextValue.gameState.levelEntitlements =
34
+ levelEntitlements as farmhand.levelEntitlements
34
35
  return (
35
36
  <FarmhandContext.Provider value={contextValue}>
36
37
  <FermentationRecipeList />
@@ -55,9 +56,8 @@ describe('FermentationRecipeList', () => {
55
56
 
56
57
  render(<FermentationRecipeListStub levelEntitlements={levelEntitlements} />)
57
58
 
58
- const cropsAvailableToFerment = getCropsAvailableToFerment(
59
- levelEntitlements
60
- )
59
+ const cropsAvailableToFerment =
60
+ getCropsAvailableToFerment(levelEntitlements)
61
61
 
62
62
  const header = screen.getByText(
63
63
  `Available Fermentation Recipes (${cropsAvailableToFerment.length} / ${totalFermentableItems})`
@@ -68,9 +68,8 @@ describe('FermentationRecipeList', () => {
68
68
 
69
69
  test('filters recipes based on search query', async () => {
70
70
  const levelEntitlements = getLevelEntitlements(100)
71
- const cropsAvailableToFerment = getCropsAvailableToFerment(
72
- levelEntitlements
73
- )
71
+ const cropsAvailableToFerment =
72
+ getCropsAvailableToFerment(levelEntitlements)
74
73
 
75
74
  render(<FermentationRecipeListStub levelEntitlements={levelEntitlements} />)
76
75
 
@@ -84,7 +83,8 @@ describe('FermentationRecipeList', () => {
84
83
 
85
84
  const filteredCrops = cropsAvailableToFerment.filter(item => {
86
85
  const itemWithName = item as farmhand.item & { name: string }
87
- const fermentationRecipeName = `Fermented ${itemWithName.name}`.toLowerCase()
86
+ const fermentationRecipeName =
87
+ `Fermented ${itemWithName.name}`.toLowerCase()
88
88
 
89
89
  return (
90
90
  fermentationRecipeName.includes('apple') ||
@@ -113,9 +113,8 @@ describe('FermentationRecipeList', () => {
113
113
 
114
114
  test('handles empty search query', async () => {
115
115
  const levelEntitlements = getLevelEntitlements(100)
116
- const cropsAvailableToFerment = getCropsAvailableToFerment(
117
- levelEntitlements
118
- )
116
+ const cropsAvailableToFerment =
117
+ getCropsAvailableToFerment(levelEntitlements)
119
118
 
120
119
  render(<FermentationRecipeListStub levelEntitlements={levelEntitlements} />)
121
120
 
@@ -28,7 +28,8 @@ export const FermentationRecipeList = () => {
28
28
 
29
29
  const filteredCrops = cropsAvailableToFerment.filter(item => {
30
30
  const itemWithName = item as farmhand.item & { name: string }
31
- const fermentationRecipeName = `${FERMENTED_CROP_NAME}${itemWithName.name}`.toLowerCase()
31
+ const fermentationRecipeName =
32
+ `${FERMENTED_CROP_NAME}${itemWithName.name}`.toLowerCase()
32
33
 
33
34
  return searchTerms.every(
34
35
  term =>
@@ -63,5 +64,3 @@ export const FermentationRecipeList = () => {
63
64
  </>
64
65
  )
65
66
  }
66
-
67
- FermentationRecipeList.propTypes = {}
@@ -10,7 +10,6 @@ import Switch from '@mui/material/Switch/index.js'
10
10
  import Tooltip from '@mui/material/Tooltip/index.js'
11
11
  import Typography from '@mui/material/Typography/index.js'
12
12
  import classNames from 'classnames'
13
- import { array, bool, element, func, number, object, string } from 'prop-types'
14
13
  import React, { memo, useEffect, useState } from 'react'
15
14
  import { GlobalHotKeys } from 'react-hotkeys'
16
15
  import { TransformComponent, TransformWrapper } from 'react-zoom-pan-pinch'
@@ -271,10 +270,6 @@ export const FieldContentWrapper = ({
271
270
  )
272
271
  }
273
272
 
274
- FieldContentWrapper.propTypes = {
275
- fieldContent: element.isRequired,
276
- }
277
-
278
273
  export const FieldContent = ({
279
274
  columns = 0,
280
275
  experience,
@@ -339,20 +334,6 @@ export const FieldContent = ({
339
334
  </>
340
335
  )
341
336
 
342
- FieldContent.propTypes = {
343
- columns: number.isRequired,
344
- experience: number.isRequired,
345
- field: array.isRequired,
346
- fieldMode: string.isRequired,
347
- handleCombineEnabledChange: func.isRequired,
348
- hoveredPlot: object.isRequired,
349
- hoveredPlotRangeSize: number.isRequired,
350
- isCombineEnabled: bool.isRequired,
351
- purchasedCombine: number.isRequired,
352
- rows: number.isRequired,
353
- setHoveredPlot: func.isRequired,
354
- }
355
-
356
337
  const adjustableRangeFieldModes = new Set<string>([
357
338
  CLEANUP,
358
339
  FERTILIZE,
@@ -597,10 +578,11 @@ export const Field = (props: FieldProps) => {
597
578
  backgroundColor: colorYellow,
598
579
  cursor: 'pointer',
599
580
  },
600
- '&.harvest-mode.is-inventory-full .Plot.crop.can-be-harvested, &.cleanup-mode.is-inventory-full .Plot.is-replantable': {
601
- backgroundColor: colorRedDanger,
602
- cursor: 'not-allowed',
603
- },
581
+ '&.harvest-mode.is-inventory-full .Plot.crop.can-be-harvested, &.cleanup-mode.is-inventory-full .Plot.is-replantable':
582
+ {
583
+ backgroundColor: colorRedDanger,
584
+ cursor: 'not-allowed',
585
+ },
604
586
  '&.cleanup-mode .Plot.is-replantable': {
605
587
  backgroundColor: colorGreenOk,
606
588
  cursor: 'pointer',
@@ -609,14 +591,15 @@ export const Field = (props: FieldProps) => {
609
591
  backgroundColor: colorGreenOk,
610
592
  cursor: 'auto',
611
593
  },
612
- '&.set-sprinkler-mode:hover .Plot:hover, &.set-scarecrow-mode:hover .Plot:hover, &.set-lightning-rod-mode:hover .Plot:hover': {
613
- '&.is-empty img': { cursor: 'pointer', opacity: 0.5 },
614
- '&:not(.is-empty)': {
615
- backgroundColor: colorRedDanger,
616
- backgroundImage: 'none',
617
- cursor: 'not-allowed',
594
+ '&.set-sprinkler-mode:hover .Plot:hover, &.set-scarecrow-mode:hover .Plot:hover, &.set-lightning-rod-mode:hover .Plot:hover':
595
+ {
596
+ '&.is-empty img': { cursor: 'pointer', opacity: 0.5 },
597
+ '&:not(.is-empty)': {
598
+ backgroundColor: colorRedDanger,
599
+ backgroundImage: 'none',
600
+ cursor: 'not-allowed',
601
+ },
618
602
  },
619
- },
620
603
  '&.set-sprinkler-mode:hover .Plot:hover.is-empty img': {
621
604
  backgroundImage: `url(${sprinklerImg})`,
622
605
  },
@@ -699,24 +682,6 @@ export const Field = (props: FieldProps) => {
699
682
  )
700
683
  }
701
684
 
702
- Field.propTypes = {
703
- columns: number.isRequired,
704
- experience: number.isRequired,
705
- field: array.isRequired,
706
- fieldMode: string.isRequired,
707
- handleCombineEnabledChange: func.isRequired,
708
- handleFieldActionRangeChange: func.isRequired,
709
- hoveredPlotRangeSize: number.isRequired,
710
- inventory: array.isRequired,
711
- inventoryLimit: number.isRequired,
712
- isCombineEnabled: bool.isRequired,
713
- isMenuOpen: bool,
714
- purchasedCombine: number.isRequired,
715
- purchasedField: number.isRequired,
716
- rows: number.isRequired,
717
- selectedItemId: string.isRequired,
718
- }
719
-
720
685
  export default function Consumer(props: Partial<FieldProps>) {
721
686
  return (
722
687
  <FarmhandContext.Consumer>
@@ -41,8 +41,9 @@ export const Forest = () => {
41
41
  // Also caps by available width (2 * columns "slots": each column, each
42
42
  // gap, and one slot split across the two side paddings) so columnGap and
43
43
  // padding below - set to this same value - shrink along with the columns.
44
- const maxPlotSize = `max(${MIN_PLOT_SIZE}, min(160px, calc((100vh - ${CHROME_HEIGHT_PX}px) / ${rows +
45
- OVERHANG_ROW_MULTIPLE}), calc(100% / ${2 * Math.max(columns, 1)})))`
44
+ const maxPlotSize = `max(${MIN_PLOT_SIZE}, min(160px, calc((100vh - ${CHROME_HEIGHT_PX}px) / ${
45
+ rows + OVERHANG_ROW_MULTIPLE
46
+ }), calc(100% / ${2 * Math.max(columns, 1)})))`
46
47
 
47
48
  // The reserve itself, in the same unit as a plot. Applying this as
48
49
  // one-sided paddingTop on .Forest (below) shifts the flexbox
@@ -80,17 +81,19 @@ export const Forest = () => {
80
81
  // Paired with ForestPlot.tsx's translateX to give staggered rows a
81
82
  // symmetric FOREST_ROW_STAGGER_OVERLAP_PX overlap on both sides -
82
83
  // see that file's comment for the shared derivation.
83
- columnGap: `calc(${maxPlotSize} - ${2 *
84
- FOREST_ROW_STAGGER_OVERLAP_PX}px)`,
84
+ columnGap: `calc(${maxPlotSize} - ${
85
+ 2 * FOREST_ROW_STAGGER_OVERLAP_PX
86
+ }px)`,
85
87
  justifyContent: 'center',
86
88
  width: '100%',
87
89
  // ForestQuickSelect switches to a fixed right-side sidebar at this
88
90
  // breakpoint (see quickSelectSx) - reserve its width so centering
89
91
  // doesn't run the grid into it. Below this breakpoint the toolbelt
90
92
  // is a bottom bar instead, so no reservation is needed there.
91
- [`@media (orientation: landscape) and (min-height: ${breakpoints.largePhone}px)`]: {
92
- width: `calc(100% - ${layout.fieldSpaceForRightSideControls})`,
93
- },
93
+ [`@media (orientation: landscape) and (min-height: ${breakpoints.largePhone}px)`]:
94
+ {
95
+ width: `calc(100% - ${layout.fieldSpaceForRightSideControls})`,
96
+ },
94
97
  // Lower bound must be MIN_PLOT_SIZE, not 0, or columns shrink past
95
98
  // it to still fit the container.
96
99
  gridTemplateColumns: `repeat(${columns}, minmax(${MIN_PLOT_SIZE}, ${maxPlotSize}))`,
@@ -42,8 +42,8 @@ const getForestPlotBackgroundImage = (
42
42
  fertilizerType === STANDARD
43
43
  ? plotStates['mulched-plot']
44
44
  : fertilizerType === RAINBOW
45
- ? plotStates['rainbow-mulched-plot']
46
- : null
45
+ ? plotStates['rainbow-mulched-plot']
46
+ : null
47
47
 
48
48
  return [
49
49
  ...(overlay ? [`url(${overlay})`] : []),
@@ -70,8 +70,8 @@ const getTreeTooltipText = (
70
70
  treeLifeStage !== GROWN
71
71
  ? 'Growing...'
72
72
  : fruitLifeStage === GROWN
73
- ? `Ready to pick! (${fruitYield} ${fruitItemName ?? 'fruit'})`
74
- : 'Fruiting...'
73
+ ? `Ready to pick! (${fruitYield} ${fruitItemName ?? 'fruit'})`
74
+ : 'Fruiting...'
75
75
 
76
76
  if (!fertilizerType || fertilizerType === NONE) {
77
77
  return growthText
@@ -310,7 +310,7 @@ export const ForestPlot = ({
310
310
  <Typography>
311
311
  {getChopYieldText(
312
312
  chopWoodRange,
313
- isFruitRipe ? item?.name ?? null : null
313
+ isFruitRipe ? (item?.name ?? null) : null
314
314
  )}
315
315
  </Typography>
316
316
  </>