@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.
- package/README.md +1 -0
- package/dist/assets/{index-DNPchtK9.js → index-Dihg7UqQ.js} +15 -15
- package/dist/assets/{index-DNPchtK9.js.map → index-Dihg7UqQ.js.map} +1 -1
- package/dist/index.html +1 -1
- package/dist/service-worker.js +1 -1
- package/dist/service-worker.js.map +1 -1
- package/package.json +4 -5
- 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 +4 -12
- package/src/components/Achievement/Achievement.tsx +0 -13
- package/src/components/AchievementsView/AchievementsView.tsx +2 -7
- package/src/components/AnimatedNumber/AnimatedNumber.tsx +0 -6
- package/src/components/AppBar/AppBar.tsx +0 -10
- 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 -5
- package/src/components/CowCard/CowCard.tsx +0 -26
- package/src/components/CowCard/Subheader/Subheader.tsx +11 -26
- package/src/components/CowPen/CowPen.tsx +4 -15
- package/src/components/CowPenContextMenu/CowPenContextMenu.tsx +0 -16
- package/src/components/CowPenContextMenu/TabPanel/index.tsx +0 -7
- package/src/components/Farmhand/Farmhand.context.tsx +4 -3
- package/src/components/Farmhand/Farmhand.tsx +4 -11
- 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 +12 -13
- 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 +13 -48
- 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 +0 -6
- 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 +3 -11
- package/src/components/Item/Item.tsx +0 -21
- package/src/components/ItemList/ItemList.tsx +4 -11
- package/src/components/KeybindingsView/KeybindingsView.tsx +0 -2
- package/src/components/LogView/LogView.tsx +0 -6
- package/src/components/Navigation/DayAndProgressContainer.tsx +0 -7
- package/src/components/Navigation/Navigation.tsx +0 -23
- package/src/components/NotificationSystem/NotificationSystem.test.tsx +4 -1
- package/src/components/NotificationSystem/NotificationSystem.tsx +5 -12
- 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/Plot/Plot.tsx +3 -3
- package/src/components/PriceEventView/PriceEventView.tsx +0 -6
- package/src/components/ProgressBar/ProgressBar.tsx +0 -5
- package/src/components/QuantityInput/QuantityInput.tsx +0 -9
- 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 +0 -6
- 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 -16
- 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 -15
- package/src/components/TierPurchase/TierPurchase.tsx +0 -12
- package/src/components/Toolbelt/Toolbelt.tsx +5 -10
- 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 +2 -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/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 +10 -0
- package/src/hooks/usePrefersReducedMotion.ts +10 -6
- package/src/mui-theme.ts +4 -3
- package/src/scripts/generate-crop-table.ts +3 -2
- package/src/styles/sx.ts +29 -25
- 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 -16
- 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/index.html
CHANGED
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
gtag('config', analyticsID)
|
|
76
76
|
})()
|
|
77
77
|
</script>
|
|
78
|
-
<script type="module" crossorigin src="./assets/index-
|
|
78
|
+
<script type="module" crossorigin src="./assets/index-Dihg7UqQ.js"></script>
|
|
79
79
|
<link rel="stylesheet" crossorigin href="./assets/index-CNcrTYN-.css">
|
|
80
80
|
<link rel="manifest" href="./manifest.webmanifest"></head>
|
|
81
81
|
<body>
|
package/dist/service-worker.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,o)=>{const r=e||("document"in self?document.currentScript.src:"")||location.href;if(s[r])return;let d={};const l=e=>i(e,r),t={module:{uri:r},exports:d,require:l};s[r]=Promise.all(n.map(e=>t[e]||l(e))).then(e=>(o(...e),d))}}define(["./workbox-2fbc6a65"],function(e){"use strict";self.addEventListener("message",e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()}),e.precacheAndRoute([{url:"index.html",revision:"
|
|
1
|
+
if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,o)=>{const r=e||("document"in self?document.currentScript.src:"")||location.href;if(s[r])return;let d={};const l=e=>i(e,r),t={module:{uri:r},exports:d,require:l};s[r]=Promise.all(n.map(e=>t[e]||l(e))).then(e=>(o(...e),d))}}define(["./workbox-2fbc6a65"],function(e){"use strict";self.addEventListener("message",e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()}),e.precacheAndRoute([{url:"index.html",revision:"1a925f166515a9c6c4a510e04760d6d2"},{url:"electron.js",revision:"b0456826f47539f6c1957c3add5eb959"},{url:"assets/workbox-window.prod.es5-Bd17z0YL.js",revision:null},{url:"assets/index-Dihg7UqQ.js",revision:null},{url:"assets/index-CNcrTYN-.css",revision:null},{url:"favicon.ico",revision:"445bb19d4a8fd46eb433dd43cbdce691"},{url:"logo192.png",revision:"70746d790b8990639d1390337d77d81a"},{url:"logo512.png",revision:"b044ab46b3f33f0e2d313d961bf1f654"},{url:"logoMaskable.png",revision:"23be58ccf16df9f43658aad3da30056d"},{url:"manifest.webmanifest",revision:"3ad071a00582451c9cdeb827b37b9ebe"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html")))});
|
|
2
2
|
//# sourceMappingURL=service-worker.js.map
|
|
3
3
|
//# sourceMappingURL=service-worker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-worker.js","sources":["../../../../../tmp/
|
|
1
|
+
{"version":3,"file":"service-worker.js","sources":["../../../../../tmp/3f6b996c04d6ac4afbf39f21d035a4a0/service-worker.js"],"sourcesContent":["import {precacheAndRoute as workbox_precaching_precacheAndRoute} from '/home/runner/work/farmhand/farmhand/node_modules/workbox-precaching/precacheAndRoute.mjs';\nimport {cleanupOutdatedCaches as workbox_precaching_cleanupOutdatedCaches} from '/home/runner/work/farmhand/farmhand/node_modules/workbox-precaching/cleanupOutdatedCaches.mjs';\nimport {registerRoute as workbox_routing_registerRoute} from '/home/runner/work/farmhand/farmhand/node_modules/workbox-routing/registerRoute.mjs';\nimport {NavigationRoute as workbox_routing_NavigationRoute} from '/home/runner/work/farmhand/farmhand/node_modules/workbox-routing/NavigationRoute.mjs';\nimport {createHandlerBoundToURL as workbox_precaching_createHandlerBoundToURL} from '/home/runner/work/farmhand/farmhand/node_modules/workbox-precaching/createHandlerBoundToURL.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\n\n\nself.addEventListener('message', (event) => {\n if (event.data && event.data.type === 'SKIP_WAITING') {\n self.skipWaiting();\n }\n});\n\n/**\n * The precacheAndRoute() method efficiently caches and responds to\n * requests for URLs in the manifest.\n * See https://goo.gl/S9QRab\n */\nworkbox_precaching_precacheAndRoute([\n {\n \"url\": \"index.html\",\n \"revision\": \"1a925f166515a9c6c4a510e04760d6d2\"\n },\n {\n \"url\": \"electron.js\",\n \"revision\": \"b0456826f47539f6c1957c3add5eb959\"\n },\n {\n \"url\": \"assets/workbox-window.prod.es5-Bd17z0YL.js\",\n \"revision\": null\n },\n {\n \"url\": \"assets/index-Dihg7UqQ.js\",\n \"revision\": null\n },\n {\n \"url\": \"assets/index-CNcrTYN-.css\",\n \"revision\": null\n },\n {\n \"url\": \"favicon.ico\",\n \"revision\": \"445bb19d4a8fd46eb433dd43cbdce691\"\n },\n {\n \"url\": \"logo192.png\",\n \"revision\": \"70746d790b8990639d1390337d77d81a\"\n },\n {\n \"url\": \"logo512.png\",\n \"revision\": \"b044ab46b3f33f0e2d313d961bf1f654\"\n },\n {\n \"url\": \"logoMaskable.png\",\n \"revision\": \"23be58ccf16df9f43658aad3da30056d\"\n },\n {\n \"url\": \"manifest.webmanifest\",\n \"revision\": \"3ad071a00582451c9cdeb827b37b9ebe\"\n }\n], {});\nworkbox_precaching_cleanupOutdatedCaches();workbox_routing_registerRoute(new workbox_routing_NavigationRoute(workbox_precaching_createHandlerBoundToURL(\"index.html\")));\n\n\n"],"names":["self","addEventListener","event","data","type","skipWaiting","workbox_precaching_precacheAndRoute","url","revision","workbox_precaching_cleanupOutdatedCaches","workbox_routing_registerRoute","workbox_routing_NavigationRoute","workbox_precaching_createHandlerBoundToURL"],"mappings":"inBAmBAA,KAAKC,iBAAiB,UAAYC,IAC5BA,EAAMC,MAA4B,iBAApBD,EAAMC,KAAKC,MAC3BJ,KAAKK,gBASTC,EAAAA,iBAAoC,CAClC,CACEC,IAAO,aACPC,SAAY,oCAEd,CACED,IAAO,cACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,MAEd,CACED,IAAO,2BACPC,SAAY,MAEd,CACED,IAAO,4BACPC,SAAY,MAEd,CACED,IAAO,cACPC,SAAY,oCAEd,CACED,IAAO,cACPC,SAAY,oCAEd,CACED,IAAO,cACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,qCAEb,CAAA,GACHC,EAAAA,wBAA2CC,EAAAA,cAA8B,IAAIC,EAAAA,gBAAgCC,0BAA2C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jeremyckahn/farmhand",
|
|
3
|
-
"version": "1.23.
|
|
3
|
+
"version": "1.23.3",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"browserslist": "^4.21.9",
|
|
69
69
|
"cheerio": "^1.0.0-rc.3",
|
|
70
70
|
"cross-env": "^7.0.2",
|
|
71
|
-
"electron": "^
|
|
71
|
+
"electron": "^41.10.6",
|
|
72
72
|
"electron-builder": "^26.0.12",
|
|
73
73
|
"esbuild": "^0.28.1",
|
|
74
74
|
"eslint": "^8.57.1",
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
"mprocs": "^0.9.6",
|
|
88
88
|
"nodemon": "^2.0.2",
|
|
89
89
|
"npm-run-all": "^4.1.3",
|
|
90
|
-
"prettier": "^
|
|
91
|
-
"pretty-quick": "^
|
|
90
|
+
"prettier": "^3.5.3",
|
|
91
|
+
"pretty-quick": "^4.0.0",
|
|
92
92
|
"serve": "^14.2.0",
|
|
93
93
|
"typescript": "^6.0.2",
|
|
94
94
|
"vercel": "^59.11.7",
|
|
@@ -134,7 +134,6 @@
|
|
|
134
134
|
"notistack": "^2.0.8",
|
|
135
135
|
"path": "npm:path-browserify@^1.0.1",
|
|
136
136
|
"process": "^0.11.10",
|
|
137
|
-
"prop-types": "^15.6.2",
|
|
138
137
|
"react": "^17.0.2",
|
|
139
138
|
"react-confetti": "6.1.0",
|
|
140
139
|
"react-dom": "^17.0.2",
|
|
@@ -1,8 +1,68 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomStream } from '../../enums.js'
|
|
2
|
+
|
|
3
|
+
import { RandomNumberService, randomNumberService } from './randomNumber.js'
|
|
2
4
|
|
|
3
5
|
const chance = 0.6
|
|
4
6
|
|
|
5
7
|
describe('RandomNumberService', () => {
|
|
8
|
+
describe('generateRandomNumber', () => {
|
|
9
|
+
let service: RandomNumberService
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
service = new RandomNumberService()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
test('returns queued numbers for a stream before random ones', () => {
|
|
16
|
+
const reference = new RandomNumberService()
|
|
17
|
+
|
|
18
|
+
reference.seedRandomNumber('123')
|
|
19
|
+
const firstSeeded = reference.generateRandomNumber()
|
|
20
|
+
|
|
21
|
+
service.seedRandomNumber('123')
|
|
22
|
+
service.queueRandomNumbers(randomStream.PRECIPITATION, [0.1, 0.2])
|
|
23
|
+
|
|
24
|
+
expect(service.generateRandomNumber(randomStream.PRECIPITATION)).toEqual(
|
|
25
|
+
0.1
|
|
26
|
+
)
|
|
27
|
+
expect(service.generateRandomNumber(randomStream.PRECIPITATION)).toEqual(
|
|
28
|
+
0.2
|
|
29
|
+
)
|
|
30
|
+
// Queued numbers don't consume seeded draws, so the seeded sequence
|
|
31
|
+
// resumes from its start
|
|
32
|
+
expect(service.generateRandomNumber(randomStream.PRECIPITATION)).toEqual(
|
|
33
|
+
firstSeeded
|
|
34
|
+
)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
test('queued numbers only affect their own stream', () => {
|
|
38
|
+
vitest.spyOn(Math, 'random').mockReturnValue(0.42)
|
|
39
|
+
service.queueRandomNumbers(randomStream.PRECIPITATION, [0.1])
|
|
40
|
+
|
|
41
|
+
expect(service.generateRandomNumber(randomStream.STORM)).toEqual(0.42)
|
|
42
|
+
expect(service.generateRandomNumber()).toEqual(0.42)
|
|
43
|
+
expect(service.generateRandomNumber(randomStream.PRECIPITATION)).toEqual(
|
|
44
|
+
0.1
|
|
45
|
+
)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('unqueued stream draws come from the shared seeded sequence', () => {
|
|
49
|
+
const reference = new RandomNumberService()
|
|
50
|
+
|
|
51
|
+
reference.seedRandomNumber('123')
|
|
52
|
+
const shared = [
|
|
53
|
+
reference.generateRandomNumber(),
|
|
54
|
+
reference.generateRandomNumber(),
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
service.seedRandomNumber('123')
|
|
58
|
+
|
|
59
|
+
expect([
|
|
60
|
+
service.generateRandomNumber(randomStream.PRECIPITATION),
|
|
61
|
+
service.generateRandomNumber(randomStream.STORM),
|
|
62
|
+
]).toEqual(shared)
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
|
|
6
66
|
describe('isRandomNumberLessThan', () => {
|
|
7
67
|
test('it returns true when random number is below chance', () => {
|
|
8
68
|
vitest
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import seedrandom from 'seedrandom'
|
|
2
2
|
import globalWindow from 'global/window.js'
|
|
3
3
|
|
|
4
|
+
import { randomStream } from '../../enums.js'
|
|
5
|
+
|
|
4
6
|
export class RandomNumberService {
|
|
5
7
|
seededRandom: (() => number) | null = null
|
|
6
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Values queued per stream name that are returned, in order, before any
|
|
11
|
+
* seeded or Math.random value. This lets tests force a specific outcome
|
|
12
|
+
* (e.g. rain tonight) without searching for a seed that happens to produce
|
|
13
|
+
* it. Exposed via the window.farmhand debug hook.
|
|
14
|
+
*/
|
|
15
|
+
queuedNumbers: Map<randomStream, number[]> = new Map()
|
|
16
|
+
|
|
7
17
|
constructor() {
|
|
8
18
|
// The availability of window.location needs to be checked before accessing
|
|
9
19
|
// its .search property. This code runs in both a browser and Node.js
|
|
@@ -21,10 +31,35 @@ export class RandomNumberService {
|
|
|
21
31
|
this.seededRandom = seedrandom(seed)
|
|
22
32
|
}
|
|
23
33
|
|
|
24
|
-
|
|
34
|
+
/**
|
|
35
|
+
* @param stream Optional name of the random number stream being drawn
|
|
36
|
+
* from, which lets queueRandomNumbers target it. Values that aren't queued
|
|
37
|
+
* come from the same seeded (or Math.random) sequence regardless of stream.
|
|
38
|
+
*/
|
|
39
|
+
generateRandomNumber(stream?: randomStream): number {
|
|
40
|
+
if (stream !== undefined) {
|
|
41
|
+
const queuedNumber = this.queuedNumbers.get(stream)?.shift()
|
|
42
|
+
|
|
43
|
+
if (queuedNumber !== undefined) {
|
|
44
|
+
return queuedNumber
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
25
48
|
return this.seededRandom ? this.seededRandom() : Math.random()
|
|
26
49
|
}
|
|
27
50
|
|
|
51
|
+
/**
|
|
52
|
+
* @param stream Name of the random number stream to queue values for.
|
|
53
|
+
* @param numbers Values to return from the stream, in order, before it
|
|
54
|
+
* resumes producing random numbers.
|
|
55
|
+
*/
|
|
56
|
+
queueRandomNumbers(stream: randomStream, numbers: number[]) {
|
|
57
|
+
this.queuedNumbers.set(stream, [
|
|
58
|
+
...(this.queuedNumbers.get(stream) ?? []),
|
|
59
|
+
...numbers,
|
|
60
|
+
])
|
|
61
|
+
}
|
|
62
|
+
|
|
28
63
|
unseedRandomNumber() {
|
|
29
64
|
this.seededRandom = null
|
|
30
65
|
}
|
package/src/common/utils.ts
CHANGED
|
@@ -1,25 +1,34 @@
|
|
|
1
1
|
import { itemsMap } from '../data/maps.js'
|
|
2
|
+
import { randomStream } from '../enums.js'
|
|
3
|
+
import { getValueAdjustmentStream } from '../utils/getValueAdjustmentStream.js'
|
|
2
4
|
|
|
3
5
|
import { randomNumberService } from './services/randomNumber.ts'
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
/**
|
|
8
|
+
* @param stream Optional name of the random number stream being drawn from.
|
|
9
|
+
* See RandomNumberService#generateRandomNumber.
|
|
10
|
+
*/
|
|
11
|
+
export const random = (stream?: randomStream) => {
|
|
12
|
+
return randomNumberService.generateRandomNumber(stream)
|
|
7
13
|
}
|
|
8
14
|
|
|
9
15
|
export const generateValueAdjustments = (
|
|
10
16
|
priceCrashes: Partial<Record<string, farmhand.priceEvent>> = {},
|
|
11
17
|
priceSurges: Partial<Record<string, farmhand.priceEvent>> = {}
|
|
12
18
|
): Record<string, number> =>
|
|
13
|
-
Object.keys(itemsMap).reduce(
|
|
14
|
-
|
|
15
|
-
if (
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
Object.keys(itemsMap).reduce(
|
|
20
|
+
(acc, key) => {
|
|
21
|
+
if (itemsMap[key].doesPriceFluctuate) {
|
|
22
|
+
if (priceCrashes[key]) {
|
|
23
|
+
acc[key] = 0.5
|
|
24
|
+
} else if (priceSurges[key]) {
|
|
25
|
+
acc[key] = 1.5
|
|
26
|
+
} else {
|
|
27
|
+
acc[key] = random(getValueAdjustmentStream(key)) + 0.5
|
|
28
|
+
}
|
|
21
29
|
}
|
|
22
|
-
}
|
|
23
30
|
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
return acc
|
|
32
|
+
},
|
|
33
|
+
{} as Record<string, number>
|
|
34
|
+
)
|
|
@@ -6,7 +6,6 @@ import Button from '@mui/material/Button/index.js'
|
|
|
6
6
|
import TextField from '@mui/material/TextField/index.js'
|
|
7
7
|
import AccountBalanceIcon from '@mui/icons-material/AccountBalance.js'
|
|
8
8
|
import NumberFormat from 'react-number-format'
|
|
9
|
-
import { func, number } from 'prop-types'
|
|
10
9
|
|
|
11
10
|
import FarmhandContext from '../Farmhand/Farmhand.context.js'
|
|
12
11
|
import { moneyString } from '../../utils/moneyString.js'
|
|
@@ -65,10 +64,10 @@ const AccountingView = ({
|
|
|
65
64
|
Math.min(loanBalance, money)
|
|
66
65
|
)
|
|
67
66
|
|
|
68
|
-
useEffect(
|
|
69
|
-
loanBalance,
|
|
70
|
-
money
|
|
71
|
-
|
|
67
|
+
useEffect(
|
|
68
|
+
() => setLoanInputValue(Math.min(loanBalance, money)),
|
|
69
|
+
[loanBalance, money]
|
|
70
|
+
)
|
|
72
71
|
|
|
73
72
|
return (
|
|
74
73
|
<Div className="AccountingView">
|
|
@@ -156,13 +155,6 @@ const AccountingView = ({
|
|
|
156
155
|
)
|
|
157
156
|
}
|
|
158
157
|
|
|
159
|
-
AccountingView.propTypes = {
|
|
160
|
-
handleClickTakeOutLoanButton: func.isRequired,
|
|
161
|
-
handleClickLoanPaydownButton: func.isRequired,
|
|
162
|
-
loanBalance: number.isRequired,
|
|
163
|
-
money: number.isRequired,
|
|
164
|
-
}
|
|
165
|
-
|
|
166
158
|
export default function Consumer(props: Partial<AccountingViewProps>) {
|
|
167
159
|
return (
|
|
168
160
|
<FarmhandContext.Consumer>
|
|
@@ -6,7 +6,6 @@ import Card from '@mui/material/Card/index.js'
|
|
|
6
6
|
import CardHeader from '@mui/material/CardHeader/index.js'
|
|
7
7
|
import CardContent from '@mui/material/CardContent/index.js'
|
|
8
8
|
import BeenhereIcon from '@mui/icons-material/Beenhere.js'
|
|
9
|
-
import { bool, object, shape, string } from 'prop-types'
|
|
10
9
|
|
|
11
10
|
import FarmhandContext from '../Farmhand/Farmhand.context.js'
|
|
12
11
|
import { Div } from '../Elements/index.js'
|
|
@@ -62,18 +61,6 @@ const Achievement = ({
|
|
|
62
61
|
)
|
|
63
62
|
}
|
|
64
63
|
|
|
65
|
-
Achievement.propTypes = {
|
|
66
|
-
achievement: shape({
|
|
67
|
-
description: string.isRequired,
|
|
68
|
-
id: string.isRequired,
|
|
69
|
-
name: string.isRequired,
|
|
70
|
-
rewardDescription: string.isRequired,
|
|
71
|
-
}).isRequired,
|
|
72
|
-
completedAchievements: object.isRequired,
|
|
73
|
-
gameState: object.isRequired,
|
|
74
|
-
isComplete: bool,
|
|
75
|
-
}
|
|
76
|
-
|
|
77
64
|
export default function Consumer(props: {
|
|
78
65
|
achievement: farmhand.achievement
|
|
79
66
|
completedAchievements?: Partial<Record<string, boolean>>
|
|
@@ -2,7 +2,6 @@ import React from 'react'
|
|
|
2
2
|
import Accordion from '@mui/material/Accordion/index.js'
|
|
3
3
|
import AccordionSummary from '@mui/material/AccordionSummary/index.js'
|
|
4
4
|
import AccordionDetails from '@mui/material/AccordionDetails/index.js'
|
|
5
|
-
import { object } from 'prop-types'
|
|
6
5
|
import Divider from '@mui/material/Divider/index.js'
|
|
7
6
|
|
|
8
7
|
import FarmhandContext from '../Farmhand/Farmhand.context.js'
|
|
@@ -23,8 +22,8 @@ const partitionAchievements = memoize(
|
|
|
23
22
|
return acc
|
|
24
23
|
},
|
|
25
24
|
{
|
|
26
|
-
complete: [] as typeof achievements[number][],
|
|
27
|
-
incomplete: [] as typeof achievements[number][],
|
|
25
|
+
complete: [] as (typeof achievements)[number][],
|
|
26
|
+
incomplete: [] as (typeof achievements)[number][],
|
|
28
27
|
}
|
|
29
28
|
)
|
|
30
29
|
)
|
|
@@ -84,10 +83,6 @@ const AchievementsView = ({
|
|
|
84
83
|
</Div>
|
|
85
84
|
)
|
|
86
85
|
|
|
87
|
-
AchievementsView.propTypes = {
|
|
88
|
-
completedAchievements: object.isRequired,
|
|
89
|
-
}
|
|
90
|
-
|
|
91
86
|
export default function Consumer(
|
|
92
87
|
props: Partial<Parameters<typeof AchievementsView>[0]>
|
|
93
88
|
) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from 'react'
|
|
2
2
|
// eslint-disable-next-line no-unused-vars
|
|
3
3
|
import { tween, Tweenable } from 'shifty'
|
|
4
|
-
import { func as funcProp, number as numberProp } from 'prop-types'
|
|
5
4
|
|
|
6
5
|
import { usePrefersReducedMotion } from '../../hooks/usePrefersReducedMotion.js'
|
|
7
6
|
|
|
@@ -55,9 +54,4 @@ const AnimatedNumber = ({
|
|
|
55
54
|
return <span className="AnimatedNumber">{formatter(displayedNumber)}</span>
|
|
56
55
|
}
|
|
57
56
|
|
|
58
|
-
AnimatedNumber.propTypes = {
|
|
59
|
-
formatter: funcProp,
|
|
60
|
-
number: numberProp.isRequired,
|
|
61
|
-
}
|
|
62
|
-
|
|
63
57
|
export default AnimatedNumber
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from 'react'
|
|
2
2
|
// eslint-disable-next-line no-unused-vars
|
|
3
3
|
import { tween, Tweenable } from 'shifty'
|
|
4
|
-
import { array, bool, func, number, string } from 'prop-types'
|
|
5
4
|
|
|
6
5
|
import { default as MuiAppBar } from '@mui/material/AppBar/index.js'
|
|
7
6
|
import Toolbar from '@mui/material/Toolbar/index.js'
|
|
@@ -192,15 +191,6 @@ export const AppBar = ({
|
|
|
192
191
|
</MuiAppBar>
|
|
193
192
|
)
|
|
194
193
|
|
|
195
|
-
AppBar.propTypes = {
|
|
196
|
-
dayCount: number.isRequired,
|
|
197
|
-
handleClickNotificationIndicator: func.isRequired,
|
|
198
|
-
money: number.isRequired,
|
|
199
|
-
showNotifications: bool.isRequired,
|
|
200
|
-
todaysNotifications: array.isRequired,
|
|
201
|
-
viewTitle: string.isRequired,
|
|
202
|
-
}
|
|
203
|
-
|
|
204
194
|
export default function Consumer(props: Partial<Parameters<typeof AppBar>[0]>) {
|
|
205
195
|
return (
|
|
206
196
|
<FarmhandContext.Consumer>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React, { useContext, useState } from 'react'
|
|
2
|
-
import { number } from 'prop-types'
|
|
3
2
|
import Divider from '@mui/material/Divider/index.js'
|
|
4
3
|
import Card from '@mui/material/Card/index.js'
|
|
5
4
|
import CardContent from '@mui/material/CardContent/index.js'
|
|
@@ -98,8 +97,3 @@ Kegs that contain wine compound in value at a rate of ${WINE_INTEREST_RATE}% for
|
|
|
98
97
|
</TabPanel>
|
|
99
98
|
)
|
|
100
99
|
}
|
|
101
|
-
|
|
102
|
-
CellarInventoryTabPanel.propTypes = {
|
|
103
|
-
currentTab: number.isRequired,
|
|
104
|
-
index: number.isRequired,
|
|
105
|
-
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { number } from 'prop-types'
|
|
3
2
|
import Divider from '@mui/material/Divider/index.js'
|
|
4
3
|
import Card from '@mui/material/Card/index.js'
|
|
5
4
|
import CardContent from '@mui/material/CardContent/index.js'
|
|
@@ -37,8 +36,3 @@ export const FermentationTabPanel = ({
|
|
|
37
36
|
</ul>
|
|
38
37
|
</TabPanel>
|
|
39
38
|
)
|
|
40
|
-
|
|
41
|
-
FermentationTabPanel.propTypes = {
|
|
42
|
-
currentTab: number.isRequired,
|
|
43
|
-
index: number.isRequired,
|
|
44
|
-
}
|
|
@@ -2,7 +2,6 @@ import Button from '@mui/material/Button/index.js'
|
|
|
2
2
|
import Card from '@mui/material/Card/index.js'
|
|
3
3
|
import CardActions from '@mui/material/CardActions/index.js'
|
|
4
4
|
import CardHeader from '@mui/material/CardHeader/index.js'
|
|
5
|
-
import { object } from 'prop-types'
|
|
6
5
|
import { useContext } from 'react'
|
|
7
6
|
|
|
8
7
|
import { itemsMap } from '../../data/maps.js'
|
|
@@ -119,7 +118,3 @@ export function Keg({ keg }: { keg: farmhand.keg }) {
|
|
|
119
118
|
</Card>
|
|
120
119
|
)
|
|
121
120
|
}
|
|
122
|
-
|
|
123
|
-
Keg.propTypes = {
|
|
124
|
-
keg: object.isRequired,
|
|
125
|
-
}
|
|
@@ -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: `cellar-tab-${index}`,
|
|
32
25
|
'aria-controls': `cellar-tabpanel-${index}`,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { number } from 'prop-types'
|
|
3
2
|
import Divider from '@mui/material/Divider/index.js'
|
|
4
3
|
import Card from '@mui/material/Card/index.js'
|
|
5
4
|
import CardContent from '@mui/material/CardContent/index.js'
|
|
@@ -37,8 +36,3 @@ export const WinemakingTabPanel = ({
|
|
|
37
36
|
</ul>
|
|
38
37
|
</TabPanel>
|
|
39
38
|
)
|
|
40
|
-
|
|
41
|
-
WinemakingTabPanel.propTypes = {
|
|
42
|
-
currentTab: number.isRequired,
|
|
43
|
-
index: number.isRequired,
|
|
44
|
-
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React, { memo } from 'react'
|
|
2
|
-
import { array, string } from 'prop-types'
|
|
3
2
|
|
|
4
3
|
import FarmhandContext from '../Farmhand/Farmhand.context.js'
|
|
5
4
|
import Inventory from '../Inventory/index.js'
|
|
@@ -61,11 +60,6 @@ export const ContextPane = ({
|
|
|
61
60
|
)
|
|
62
61
|
}
|
|
63
62
|
|
|
64
|
-
ContextPane.propTypes = {
|
|
65
|
-
playerInventory: array.isRequired,
|
|
66
|
-
stageFocus: string.isRequired,
|
|
67
|
-
}
|
|
68
|
-
|
|
69
63
|
export default function Consumer() {
|
|
70
64
|
return (
|
|
71
65
|
<FarmhandContext.Consumer>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React, { memo } from 'react'
|
|
2
|
-
import { object } from 'prop-types'
|
|
3
2
|
import Tooltip from '@mui/material/Tooltip/index.js'
|
|
4
3
|
|
|
5
4
|
import { cowColors } from '../../../enums.js'
|
|
@@ -48,8 +47,4 @@ const Bloodline = ({
|
|
|
48
47
|
</Ul>
|
|
49
48
|
)
|
|
50
49
|
|
|
51
|
-
Bloodline.propTypes = {
|
|
52
|
-
colorsInBloodline: object.isRequired,
|
|
53
|
-
}
|
|
54
|
-
|
|
55
50
|
export default memo(Bloodline)
|
|
@@ -10,7 +10,6 @@ import TextField from '@mui/material/TextField/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, func, number, object, string } from 'prop-types'
|
|
14
13
|
import { useIsMounted } from 'usehooks-ts'
|
|
15
14
|
|
|
16
15
|
import { PURCHASEABLE_COW_PENS } from '../../constants.js'
|
|
@@ -374,31 +373,6 @@ export const CowCard = ({
|
|
|
374
373
|
)
|
|
375
374
|
}
|
|
376
375
|
|
|
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
376
|
export default function Consumer(
|
|
403
377
|
props: Pick<CowCardProps, 'cow' | 'isCowOfferedForTradeByPeer' | 'isSelected'>
|
|
404
378
|
) {
|
|
@@ -6,7 +6,6 @@ import FormControlLabel from '@mui/material/FormControlLabel/index.js'
|
|
|
6
6
|
import Tooltip from '@mui/material/Tooltip/index.js'
|
|
7
7
|
import Typography from '@mui/material/Typography/index.js'
|
|
8
8
|
import classNames from 'classnames'
|
|
9
|
-
import { array, bool, func, object, string } from 'prop-types'
|
|
10
9
|
|
|
11
10
|
import { huggingMachine } from '../../../data/items.js'
|
|
12
11
|
import { genders } from '../../../enums.js'
|
|
@@ -37,18 +36,17 @@ const getCowMapById = memoize((cowInventory: farmhand.state['cowInventory']) =>
|
|
|
37
36
|
)
|
|
38
37
|
)
|
|
39
38
|
|
|
40
|
-
export interface SubheaderProps
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
> {
|
|
39
|
+
export interface SubheaderProps extends Pick<
|
|
40
|
+
CowCardProps,
|
|
41
|
+
| 'cow'
|
|
42
|
+
| 'cowBreedingPen'
|
|
43
|
+
| 'cowIdOfferedForTrade'
|
|
44
|
+
| 'cowInventory'
|
|
45
|
+
| 'handleCowAutomaticHugChange'
|
|
46
|
+
| 'handleCowBreedChange'
|
|
47
|
+
| 'huggingMachinesRemain'
|
|
48
|
+
| 'playerId'
|
|
49
|
+
> {
|
|
52
50
|
canCowBeTradedFor: boolean
|
|
53
51
|
cowValue: number
|
|
54
52
|
isCowPurchased: boolean
|
|
@@ -210,16 +208,3 @@ const Subheader = ({
|
|
|
210
208
|
}
|
|
211
209
|
|
|
212
210
|
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,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
|
}
|
|
@@ -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>
|