@jeremyckahn/farmhand 1.24.2 → 1.24.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 (27) hide show
  1. package/dist/assets/{index-C9kG86vs.js → index-CUCDQafy.js} +6 -6
  2. package/dist/assets/{index-C9kG86vs.js.map → index-CUCDQafy.js.map} +1 -1
  3. package/dist/index.html +1 -1
  4. package/dist/service-worker.js +1 -1
  5. package/dist/service-worker.js.map +1 -1
  6. package/package.json +1 -1
  7. package/src/components/CowPen/Cow.tsx +50 -6
  8. package/src/img/animals/cows/cow-variation-1-blinking.piskel +1 -0
  9. package/src/img/animals/cows/cow-variation-1-blinking.png +0 -0
  10. package/src/img/animals/cows/cow-variation-2-blinking.piskel +1 -0
  11. package/src/img/animals/cows/cow-variation-2-blinking.png +0 -0
  12. package/src/img/animals/cows/cow-variation-3-blinking.piskel +1 -0
  13. package/src/img/animals/cows/cow-variation-3-blinking.png +0 -0
  14. package/src/img/animals/cows/cow-variation-4-blinking.piskel +1 -0
  15. package/src/img/animals/cows/cow-variation-4-blinking.png +0 -0
  16. package/src/img/animals/cows/cow-variation-5-blinking.piskel +1 -0
  17. package/src/img/animals/cows/cow-variation-5-blinking.png +0 -0
  18. package/src/img/animals/cows/cow-variation-6-blinking.piskel +1 -0
  19. package/src/img/animals/cows/cow-variation-6-blinking.png +0 -0
  20. package/src/img/animals/cows/cow-variation-7-blinking.piskel +1 -0
  21. package/src/img/animals/cows/cow-variation-7-blinking.png +0 -0
  22. package/src/img/animals/cows/rainbow-cow-blinking.piskel +1 -0
  23. package/src/img/animals/cows/rainbow-cow-blinking.png +0 -0
  24. package/src/img/index.ts +21 -0
  25. package/src/utils/__snapshots__/getCowImage.test.ts.snap +2 -0
  26. package/src/utils/getCowImage.test.ts +14 -0
  27. package/src/utils/getCowImage.ts +20 -6
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-C9kG86vs.js"></script>
78
+ <script type="module" crossorigin src="./assets/index-CUCDQafy.js"></script>
79
79
  <link rel="stylesheet" crossorigin href="./assets/index-CaYdR-lC.css">
80
80
  <link rel="manifest" href="./manifest.webmanifest"></head>
81
81
  <body>
@@ -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:"f5ce8c2d4c7358bc1ce3bb4838506540"},{url:"electron.js",revision:"b0456826f47539f6c1957c3add5eb959"},{url:"assets/workbox-window.prod.es5-Bd17z0YL.js",revision:null},{url:"assets/index-CaYdR-lC.css",revision:null},{url:"assets/index-C9kG86vs.js",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")))});
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:"0dc0d9761bc8d5c79b0bebea8721a714"},{url:"electron.js",revision:"b0456826f47539f6c1957c3add5eb959"},{url:"assets/workbox-window.prod.es5-Bd17z0YL.js",revision:null},{url:"assets/index-CaYdR-lC.css",revision:null},{url:"assets/index-CUCDQafy.js",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/5a47feca681fd14fa867c579d860224e/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\": \"f5ce8c2d4c7358bc1ce3bb4838506540\"\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-CaYdR-lC.css\",\n \"revision\": null\n },\n {\n \"url\": \"assets/index-C9kG86vs.js\",\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,4BACPC,SAAY,MAEd,CACED,IAAO,2BACPC,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"}
1
+ {"version":3,"file":"service-worker.js","sources":["../../../../../tmp/ec95ff6fa943db8bc2c8e07b56a7b4ba/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\": \"0dc0d9761bc8d5c79b0bebea8721a714\"\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-CaYdR-lC.css\",\n \"revision\": null\n },\n {\n \"url\": \"assets/index-CUCDQafy.js\",\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,4BACPC,SAAY,MAEd,CACED,IAAO,2BACPC,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.24.2",
3
+ "version": "1.24.3",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -18,6 +18,10 @@ const randomPosition = () => 10 + random() * 80
18
18
  const flipAnimationDuration = 1000
19
19
  const transitionAnimationDuration = 3000
20
20
 
21
+ const blinkAnimationDuration = 200
22
+ const minBlinkAnimationInterval = 2000
23
+ const blinkAnimationIntervalVariance = 4000
24
+
21
25
  // This MUST be kept in sync with the `animationDuration` of the `.is-animating`
22
26
  // rule in CowPen.tsx.
23
27
  const hugAnimationDuration = 750
@@ -43,7 +47,11 @@ export const Cow = ({
43
47
  playerId,
44
48
  isSelected,
45
49
  }: CowProps) => {
46
- const [cowImage, setCowImage] = useState(pixel)
50
+ const [cowImages, setCowImages] = useState({
51
+ normal: pixel,
52
+ blinking: pixel,
53
+ })
54
+ const [isBlinking, setIsBlinking] = useState(false)
47
55
  const [isTransitioning, setIsTransitioning] = useState(false)
48
56
  const [moveDirection, setMoveDirection] = useState<CowMoveDirection>(RIGHT)
49
57
  const [rotate, setRotate] = useState(0)
@@ -143,14 +151,20 @@ export const Cow = ({
143
151
  [tweenable]
144
152
  )
145
153
 
146
- // Loads the cow's image on mount.
154
+ // Loads the cow's image and blinking image on mount.
147
155
  useEffect(() => {
148
156
  ;(async () => {
149
- const loadedCowImage = await getCowImage(cow)
157
+ const [loadedCowImage, loadedBlinkingCowImage] = await Promise.all([
158
+ getCowImage(cow),
159
+ getCowImage(cow, { isBlinking: true }),
160
+ ])
150
161
 
151
162
  if (isMounted() === false) return
152
163
 
153
- setCowImage(loadedCowImage)
164
+ setCowImages({
165
+ normal: loadedCowImage,
166
+ blinking: loadedBlinkingCowImage,
167
+ })
154
168
  })()
155
169
  // Mount-only effect (the function-component equivalent of
156
170
  // `componentDidMount`): it must run exactly once, so `cow` is
@@ -158,6 +172,33 @@ export const Cow = ({
158
172
  // eslint-disable-next-line react-hooks/exhaustive-deps
159
173
  }, [])
160
174
 
175
+ // Repeatedly blinks the cow: closes its eyes for `blinkAnimationDuration`, then
176
+ // waits a randomized interval before blinking again.
177
+ useEffect(() => {
178
+ let blinkAnimationTimeoutId: ReturnType<typeof setTimeout>
179
+
180
+ const scheduleNextBlink = () => {
181
+ blinkAnimationTimeoutId = setTimeout(() => {
182
+ if (isMounted() === false) return
183
+
184
+ setIsBlinking(true)
185
+
186
+ blinkAnimationTimeoutId = setTimeout(() => {
187
+ if (isMounted() === false) return
188
+
189
+ setIsBlinking(false)
190
+ scheduleNextBlink()
191
+ }, blinkAnimationDuration)
192
+ }, minBlinkAnimationInterval + random() * blinkAnimationIntervalVariance)
193
+ }
194
+
195
+ scheduleNextBlink()
196
+
197
+ return () => {
198
+ clearTimeout(blinkAnimationTimeoutId)
199
+ }
200
+ }, [isMounted])
201
+
161
202
  // Cancels any in-flight tween on unmount; `move` handles the resulting
162
203
  // rejection in its `catch` blocks.
163
204
  useEffect(() => {
@@ -235,7 +276,7 @@ export const Cow = ({
235
276
  className={classNames('cow', {
236
277
  'is-transitioning': isTransitioning,
237
278
  'is-selected': isSelected,
238
- 'is-loaded': cowImage !== pixel,
279
+ 'is-loaded': cowImages.normal !== pixel,
239
280
  })}
240
281
  onClick={() => handleCowClick(cow)}
241
282
  style={{
@@ -259,7 +300,10 @@ export const Cow = ({
259
300
  <div {...{ style: { transform: `rotateY(${rotate}deg)` } }}>
260
301
  <img
261
302
  {...{
262
- src: cowImage,
303
+ src:
304
+ isBlinking && cowImages.blinking !== pixel
305
+ ? cowImages.blinking
306
+ : cowImages.normal,
263
307
  }}
264
308
  alt={cowDisplayName}
265
309
  />
@@ -0,0 +1 @@
1
+ {"modelVersion":2,"piskel":{"name":"cow-variation-1-blinking","description":"","fps":12,"height":48,"width":48,"layers":["{\"name\":\"Layer 1\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAC4klEQVR4AeyXDXLqMAyEnXfJ3gDOBDfoKfP0ZbxUceTYSaCUmXSy6F/W2g5T/qUP/zsJvPsAzxM4T+DgDpxX6OAGHi4/T+DwFh5scJ7AwQ08XM4JjLmLZDY/Q0AgXS6XjxyeLZ4IoLwQbI7HnqV8PfqjBwSG+/2OY+BjI2jWQtmSfPnQ10AecaQHPpAg4AMtnaIH7Opx/UI0Gk09VD+OY/KQ33qQZ6L+9BKg0ajGkvW27Qg9Wlk9OS0Cs8FbC/bGy8Gu1+uj1Os4y1x8GdOVXyPw2PFcsEmwMCiL5MvvXRme2cpRjQUZWjAzVd+Bafgp4+AHiwPaSErXgNgliPn8Mi7bnwDXBX9leELPAwPSTdJfHfkkyatBBIac8CvDsxa7K2B7yI/0/kgXAWIigf7ruN1uu9b0BHY1UNHeAVSP9NcIuwdPI7Bn8Z4BWzmrBLSrSNBqthbnPq+9lHs3YEGAQQUNRHOAHx8SSEcK8st+tVwQiBYsh4IMIFdSOd6WjzyvY3twMhGUQ8z08EumJDDYn+X+PFpYkoh0JMCnwdHxYQPZyPIaMRgYv79TBGKA2hpKAmEegwCCGg6JDaQjgXIVwwbERILBNPTw9ZUA+QAdKI6vhi4CLAzKJgyFD+nj6ALxCAwX+SNfztV/CrOULgKzCjMYzkTyEhL4kEA6EigXvQQDAvnRgew1uUqA9wGsNSDGwAwoiQ/g87LUsQHXBekR+Xxc+ioBktgJSADsCOWgsqNcfPz68gNOa+T3AD/ARy7ANtn1LWR5y0fNIOGxzGx7VC8SebjFtxCdiAHTw+HNX/09QGwCDQAGiyINNLRZhmQfm5BrTaTpdzAK/SNYbMgwET/NK2RlNHksZrZ/iG2Fr5dOj2mNYpMUr8oeAtXivxDoJqCr8sqh96wREtjTaCuxZ60REgiG4Y56BCmHXb4/elfDiADFHl2NZkltw/dHb1dUMiICldS/6T4JvPtczhN49wn8BwAA//82HUsEAAAABklEQVQDAG3UeHBCTVueAAAAAElFTkSuQmCC\"}]}"]}}
@@ -0,0 +1 @@
1
+ {"modelVersion":2,"piskel":{"name":"cow-variation-2-blinking","description":"","fps":12,"height":48,"width":48,"layers":["{\"name\":\"Layer 1\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAC5ElEQVR4AeyXC3LbMAxEtb1kbmCfyb5BTunysYIGhkFKjOS6nVFGG/xBLEk58a/pP/85CXz6AM8TOE9g5w6cV2jnBu4uP09g9xbubHCewM4N3F1+nsDuLdzZ4G+cwKPM6FHM4cfXoy8N9hKg2RqWxWaF/Fmd0HsgjzjSAx+YRglQtOByuUwt+NUSvfZ4PB5TD6WOvCLaz1YCNHrEYdtt1yP0ul6vE4jZ+AA5MRbtNQJPg8fin9pbBrPenVyR0yOw7DiJo2Bhrkesw4/vfr8jurAcqynJDG0o5tR8B+rwNeOHv263W70ekLABTNIS3QbEjiBGTvRHOzuBxvCxtG9zh8kwie7BgNgm0Q3mM2n+TEYChwzP7meLeR+7a/B+dPMjsXvwBHhh01wGAmkwOLfmhbInc6SHEWB4PXWZjZFmc0m9+6a/WxqBd68z3H/rxjUJ8AIBScuO9poSA61Juc/0i/FeTS9mfYwA14drNLEIIIFFATafJgC/B4uA6PN2S491Wd5ajhGgFhLL/zY4GBxAAttAU4P5RiX1ViNpkl5hcWYougpeHk+AoObkhUgcniROwgNfhB/QYvSy/vgk1cEf399TBulPnNwWIoFWXtcPmSyhR0LSMrS+viZgPdCBkTJ/Jg8hkDVe8zHcWo7F59z6jprP5GEERk7BFjfJgKBlmz+TXQLcV5AVZr4eCa6TIdZyXbb4Yg52lwAJ7AwkAPYR4D9UPzRrYHvgs7XwF10FL09KgJ3ymdYMEh4+Z4suqX7qSOUFLl8nGQxQyxoe+IiBoqsgfVICPpMGAB8fg8gCGtaPXE8IXdIypPSsW12R9eEkUOifocQ0o4j8aRJwp0CT+nfB+awbsRFYXZT0WL7gz8Hqm/WmaBKIFcnwMeUj9mYCkurVeOeU0vgaKQFpvNEoMemYNVICyTAqPo9iHv74/uibFsgIUOyxqdFT0rrh+6OvVzQyMgKN1H/TfRL49LmcJ/DpE/gNAAD//3r5kyQAAAAGSURBVAMAr+1rcNRc4p4AAAAASUVORK5CYIIA\"}]}"]}}
@@ -0,0 +1 @@
1
+ {"modelVersion":2,"piskel":{"name":"cow-variation-3-blinking","description":"","fps":12,"height":48,"width":48,"layers":["{\"name\":\"Layer 1\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAChUlEQVR4AeyXjXEqMQyEjzSZDiiKDlIl0eewN8LIf/gSyIzf3CJZWsla+2BePrZ//m8JePUFrhtYNzB5AusVmjzA6fJ1A9NHONlg3cDkAU6XrxuYPsLJBn9xA1eb0cOWw4+vx98bzAqgWQv7ZjcH/s3d8GuARx7rQQxsowIo2nE+n7cS/G6Bn3qUahW3Onhmyk+vABpd1Vi23LadoUeL1cNpCbgbvLVhb75nMPWqcE9wagL2E4c4CjYGeV0Uyzn52tUwtJBoJQFp+MSwj8vlsgm2HHrYHFAki38UIgEPw/9sdtynDgMbdSUuRHkfywXcDe+JR/rcBKAng2IFrckDxUvWC+ALW+KleN6QzSIkcscH/YCnsgY+VvMlgOH5cjxwaSY8JN8gIAFDo+jUh4p+iTwsgOFrs3BbUZ54qzaqa8WGBbQa/nX+LQRwMxF0GOTMD7+juYDTjWz845/8NWIvcP362iKQA7VJEKDffn6JatxmjgE9ic2Bj8EhBjT06fNzA+LhA+UVjywCongxxgBRMo8zoHj4QGssw2F7cOOGB5wEWPPw/So1Z9gcJW5PnAGBuPhA65pFgIaX3fkmLP0nbg8MOAgcoCcqr42QAh0fCKjSOIlnhXgRuc+gfmPW7CXkOVs/HLDF+v6kpClkCZEl1gKDA3iqwxJjaEBOe+AL5ICtw+Et3hZAAwCZTbEGGqafXIbpherMpkf96B/BSGkfs8Wn+QpZJU3SH+/m5w+5EeT1WtMj7SFRlkgxs9WnR0C1wauT3QL0mvzmwM/sEQp4ptGosKP2CAUEw/A+egSU6ZDvj9/VMBJAsUdXoztSe+H747crCoxIQIH6nuEl4NX3sm7g1TfwDQAA//9EngZ8AAAABklEQVQDAPmFUXBZV/YBAAAAAElFTkSuQmCC\"}]}"]}}
@@ -0,0 +1 @@
1
+ {"modelVersion":2,"piskel":{"name":"cow-variation-4-blinking","description":"","fps":12,"height":48,"width":48,"layers":["{\"name\":\"Layer 1\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAADCklEQVR4AeyXi3HjMAxExWsyHdg12R2kSh0ew9VBFEhJw3OczCijDcDFhwtSzsR/pl/+cw3w7gu8buC6gcETuF6hwQMcLr9uYPgIBxtcNzB4gMPl1w0MH+Fgg++4gdk0etjy9OPr8ZcGowPQbA/LZsUhv7gTfg/kEcd6wIHp7AAULZjneWrB7xb4ucftdgvr4YHVkWem/RwdgEZgtaFve7/f/XLXLwKnXp1yes32BkA0WITXzRAA4LEC6xaOCFNtJzeR0xsgC6cBrwnJER6PR0RP1IE6GHF1Tr12NYgWclprgEV8zrJfnKyZ5WEtLGTgMLwEyD6fz1VmSmj6olL658PUuXAe0QAb8RQ8Hl8nfUQ0+QL58l9h6wFC8f97Y26CkxW4Je2BLx5LrmKR9QPsio9Os/UZiDbzHMIEz+OLx7LuQQMgfv3ylaqewF6slL/caIDNRogDm0BFRLdSpbx0uRkA0aDeVUKJCeR4nzWIOF4H3mnie6B+L0fxzQAKRPZM46g+4lo9W3zd4/AAdUNuRKCp4rLE4IE4fA/xKaUppS0ULzeXfK38eoBkP4qFVsJoDkjynF/je/jXiFr2AvPn5xSBWBHv26x8BphpbCx/icz0HzauM2qOtYfPZy9EIU6i08fHBJSHDxQXH1kGiPgNxymDOoBQcYpjgfjIIi7iI67khgecB7ATCd8v3wyhAK4ljngvRm0EBALF8IHWPcsAEi+75HPNYCGKg1BcL9b7xM6A16XOj7g6hzUDYJvgJBgC1EkaxPNwAjyDAXzxfA68wLxH+RzAAzhqAGuzmwM27thXSjVjCA8aCIiT7y08gFOtvbL5+wLCADH28IAjBswPxRu/PwANAMn8p4g10ND0pPDvtwVCXnVm88NN4NA/gsVSgZn42X2FrIwm+Sul+fVD7Azqeq3pkW9FQ1kgc2a7z5EBug3eHTw8gF6LVwrmswHO7BEO8FPFRoOFAwSJvI8eQcow5fvjH2oYDUCxx6FGq6T9he+Pv1/RyIgGaKT+TPoa4N33ct3Au2/gLwAAAP//wOsxRAAAAAZJREFUAwCUT5Bw3sIsRgAAAABJRU5ErkJgggAA\"}]}"]}}
@@ -0,0 +1 @@
1
+ {"modelVersion":2,"piskel":{"name":"cow-variation-5-blinking","description":"","fps":12,"height":48,"width":48,"layers":["{\"name\":\"Layer 1\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACz0lEQVR4AeyXCXLCMAxFrV6yN4AzwQ16yjTPRCA78kZSoDNh+GiX9W2H0q/wz18HgXcf4HECxwls3IHjCm3cwM3lxwls3sKNDY4TGNzAac4Hs+h+k69YFb3yBBhiNUDD0ayBgCapbPTcJfzsWqs6CITT6bQK7DLmo8mf9Y8EHusMawzWg1LjVm2p7u6HgFyvVxzCRwPJgvPJcXpFTNMUQKHnpPXkWKi/UJe4IZA4CkYcXBurLOTe3efzOeoMFxXzQQ9juqqTs9rkFoE4OAMAd5WGU0nYNGcwG070Vm6NQDxiO/jlckmaP2PYgZarGyxJ1TXGGrYG26JEIA5vE/fQ80Gw7aC6Bj5iatekRyAZXnckhJDsVK1pT4whAbkqrY4P4KshJ5AMXyvsjZWuHTtsof24sp5f47lUAjzdPLB5PLFLwyRJLzaUAMtCArkbXkHYEtht8NFGOdHcrvVrEsibYStqjYnZLwDudc9DSd0ImgRKzexwpRz1j+RqTa8sEvB2mUEULEAO0iL3kW/jni4iQSSFPa1FF682JxB/2OVDeIWao9LLyX35NWIwMP38BA/EQN7H2jkBG4u67qDK6Mw+IKHIQitTSTCYDi3f3wFoMjrQuPo9WSVQGpphvWYjPobrzV9y3b9TVQJ2AYZWWL+nax7Si+c+BgTqRwdq12SVAMcMag32jHFtwEjPKgEasRMiEr8lsEfBKVhQz3OQD2ptq5O/2IKeo0mAAkggRSQSEblJfCMQkcCJAiWxDBe/hbTXfb3Hwy0ay2WTAAsACvmliJxBQ5lfCaGWrXWzjG9IoNAfoAN0MOtxnVkW300CcyVNSv+cExvB3O721mt1swI94hrZJi3hsughUK7+gEg3Ab0efznzM2u4BJ5pNEpsrzVcAs4w3FELJ2Wzy/ZH72roEaDYoqtRktQ2bH/0dkUhwyNQSP1M90Hg3edynMC7T+AXAAD//zgj3voAAAAGSURBVAMA67xIcBP9HhIAAAAASUVORK5CYIIA\"}]}"]}}
@@ -0,0 +1 @@
1
+ {"modelVersion":2,"piskel":{"name":"cow-variation-6-blinking","description":"","fps":12,"height":48,"width":48,"layers":["{\"name\":\"Layer 1\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACjUlEQVR4AeyXC1LDMAxEUy7JDXqo3oBTFj/TzWw88id1S2AmTBbL0molxW4ZPpZ//nMOcPQBnidwnsDkGziv0OQLnE4/T2D6FU4KnCcw+QKn088TmH6FkwK/cQL31KMjbXc/no+9CswOgFgPa7GHAf9hLtgtwCPO6sAHlr0DkORw0dW+Xq+rXTGyBrwWUi68tNSf0QEQAnWlnREa76WMcHoD0DTo1VrjI0VHOBJscC9wWgPsahwxB4WB+15g07SQ5WoD3CkOMmviFxrAJW6321JC8dLPXrFojQbIzYtM8R90P5hKGV6ly6okbEG+1loOsGm+TES49Pm+F3cuNm8XYDvwAffVbB9g+s7XirzTrwFong9Ht5a/ZWyhm/gmggbYJf/KptEqi0e+kqP9UwMo2VfubAt7mkIXPsBuoTqAN9MSEK/FiWI0B6KY+3ocDcD953Owfj+TKNCki8qu+RWvreh6DJ0Izkk2PaZl+2gAvBDAQgEXZA9hFqWOaty/vpYIirfq+gAbHsWETeDJDc2QiiY2UNOXz88FEAfYQHF8NVQHqCW8yk9zo1oPbr7iZc5hA3gjNAjkwwbat9bmABwzqAlwHWqx0t/icl1KfuQrOeybA0DgTTAEYF+CxgSPyae1jHmD1GDvwKcc/MnOXzBp3TzdAWBLjCEcxBxqltX9sj0XDo0B4tRw4CMGkh02n/z9/4kRAJApypqA4MUbGrGVl9b8SA/9CImU66S1+oycACL5b0OgQmwPAonsQiPX0FDJm31pbT4jAzQFjg4OD6Ar8s6Gn6kRDvCM0N7BXlUjHCBohvvoCCjTLtfHHhKMBiDZMSS0IfU3ro/dz6gwogEq1L/pPgc4+lzOEzj6BL4BAAD//9HdgZsAAAAGSURBVAMAlBRicJihbigAAAAASUVORK5CYIIA\"}]}"]}}
@@ -0,0 +1 @@
1
+ {"modelVersion":2,"piskel":{"name":"cow-variation-7-blinking","description":"","fps":12,"height":48,"width":48,"layers":["{\"name\":\"Layer 1\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACsklEQVR4AeyXAXLrIAxE4V+yN0jOlNygp/TXY7wehYANJk3aGTreSohl0YKbtv/CH/+aBj59gfMG5g0MnsB8hQYPcHj5vIHhIxwUmDcweIDDy+cNDB/hoMA7bmCxHj1s2P349eSbwKgBxI6wbbYm8Nc0kO8BHvNED2og9BpgkYcX3fLL5bLllSRpwAPLsgQPasDWwrNQf1oNILQgKtQl22bQEfN6vSp9iJ7zMOEGRwZS4/BzMcaAuVcBI8Dr7ewR4e0ZoHk4Cff7PcWWb3DZGOR8aiCv5437ecenaSFRagYemk/Mzm+YAGwOWK5InbHgxz5nPh9T8ygZqDQfQi6Wj72w8haOuGdibqDa/Bnx2hpuAmMCY7i32y2Qq05kzFwN3sBh80ditU1KdbQE5mmeCFQnMt6DDNA8PxxVbi7G6VTJnRO+eZ+3yMjAxqVRsBUsycdW+jXPkwF1RtOCaiMRrVfemnqpGhChFmmoNtdb53cA6F0H/7QBFmMCkJfAHCjN+Ro3A2KMIcaYPq4Zi7PmUWMfcwNxJXvOYV5qslbz+uRg+f4OJTAH9hrAQPojzUh8Elk49/iGfZ6rMUdTQE3Hr68AxCUHmle9FDFQqp+q0RxoWUxzLTw4K7d4wMmAnUbx/WLxO0CDQHuRA433IgbUvOLGN2PpB2orvDHhFWrZDgO7PE7i1UZ4zfIGGXuwrxqjbvnTAVut7V9KicmIIgI90DqiTKzNPX0KocscsLzYvNWPDSAAILMp0YBg+silmVZoncX0SA/9EoyU9rFYfQ5fIVuJSPoz1/L8Ya4H+XqN0Uh7yJRNpJrF3afFwK7ApyebDeg1+cmGz+xRNHBGqNfYq/YoGig0w/voUaAMl7w+eZNgyQCLPZqEHkjHA69PfryiwigZqFB/Z3ka+PS9zBv49A38BwAA//+PREyqAAAABklEQVQDAJH+TnAyO6DCAAAAAElFTkSuQmCC\"}]}"]}}
@@ -0,0 +1 @@
1
+ {"modelVersion":2,"piskel":{"name":"rainbow-cow-blinking","description":"","fps":12,"height":48,"width":48,"layers":["{\"name\":\"Layer 1\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAC50lEQVR4AeyYPZLUMBCF2yQUBfcg4BZcYrkBMRkJEQkZMTdgT0DGLQi4B1UUkdEnqz1tqzWSV96Z2SpP+Y1aLXXrPf15d57JE/8cAq69gMcKHCvQOQPHFuqcwO7wYwW6p7AzwbECnRPYHX6sQPcUdia4xAqMgaNFqG5+bDz2nKBXAMlqmAdLBv2TKdjnQD/aKS3wAdkqgKAZH8f3soaM/yTCDpfbMcf4560AmyPGnnLQL482nlYBJAImtM+EeDXDp/qQNQFkANlYTQSyqMkxfn0zGS3fZRED4ecEuMQJasJpGyy6W/LDq5+LtkVleH6qnkRAWhHbSwLOkt80+whJBCx5RiePKwLyxNGpAk9AgfyUiUEnq+8b4oAsX4ZvFBMgj0X5mcmmUsZawEXIQ4eJUHAL4Ytg5hVp5aK/8GUF7EOembMoDLyXWwVA3l0v9i1oGXCxFTQAMQ1bQbtvLVVAFgdpkDUUHC75Qt893ZkASIM9B9Fcw4dfau5WZgJ2y3yhRDchgO2nEM6MQidhOkPuGV0LGB5jmZUHpc3PewCM9/fiQSAOCCwAASP3cWjnJgrFIz/hbkeEJT7c3QnQkbGBilK/VyJAhpc/vLZNvsXLyIsMxAWkNsgls1qkvu4ERwFh37n7q5p51SGK4C268lvi6ybqEATYABtg14AAJa/lHBOX+iFXHyIs5oy+wXZZt3i+dR/qCKAsgpmIQs796VuMLjSErWQJxjHSOcAP8Gk09WBnExx8bf9SajIOngUJNoEbJeGF/I4HN5HLbiHy0gaC7ZIP/roAEgA6mzc0CQe9u20ZzpNkSKRFJMZJ+iACk/weQtuif6hnT3ULhQiSiCEfXPND2xbMgSuDHPI9/EgBUlv0JbtYtAgoBt9CQ7OAeJAfciNtUPku7DCwIcQ/A5cg+1deC9hC1uvbugLsRwsvV6/P5sduyucJINiiKdGiU71i82PXIwo9PAGFrrfpPgRce12OFbj2CvwHAAD//7rOgnEAAAAGSURBVAMAF6QgcGBcpGoAAAAASUVORK5CYIIA\"}]}"]}}
package/src/img/index.ts CHANGED
@@ -269,6 +269,15 @@ import cowVariation5 from './animals/cows/cow-variation-5.png?dataUri'
269
269
  import cowVariation6 from './animals/cows/cow-variation-6.png?dataUri'
270
270
  import cowVariation7 from './animals/cows/cow-variation-7.png?dataUri'
271
271
 
272
+ import cowVariation1Blinking from './animals/cows/cow-variation-1-blinking.png?dataUri'
273
+ import cowVariation2Blinking from './animals/cows/cow-variation-2-blinking.png?dataUri'
274
+ import cowVariation3Blinking from './animals/cows/cow-variation-3-blinking.png?dataUri'
275
+ import cowVariation4Blinking from './animals/cows/cow-variation-4-blinking.png?dataUri'
276
+ import cowVariation5Blinking from './animals/cows/cow-variation-5-blinking.png?dataUri'
277
+ import cowVariation6Blinking from './animals/cows/cow-variation-6-blinking.png?dataUri'
278
+ import cowVariation7Blinking from './animals/cows/cow-variation-7-blinking.png?dataUri'
279
+ import rainbowCowBlinking from './animals/cows/rainbow-cow-blinking.png'
280
+
272
281
  export { default as pixel } from './pixel.png?dataUri'
273
282
 
274
283
  export const plotStates = {
@@ -581,6 +590,8 @@ export const tools = {
581
590
  export const animals = {
582
591
  cow: {
583
592
  rainbow: rainbowCow,
593
+ rainbowBlinking: rainbowCowBlinking,
594
+
584
595
  variations: [
585
596
  cowVariation1,
586
597
  cowVariation2,
@@ -590,5 +601,15 @@ export const animals = {
590
601
  cowVariation6,
591
602
  cowVariation7,
592
603
  ],
604
+
605
+ blinkingVariations: [
606
+ cowVariation1Blinking,
607
+ cowVariation2Blinking,
608
+ cowVariation3Blinking,
609
+ cowVariation4Blinking,
610
+ cowVariation5Blinking,
611
+ cowVariation6Blinking,
612
+ cowVariation7Blinking,
613
+ ],
593
614
  },
594
615
  }
@@ -1,3 +1,5 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
+ exports[`getCowImage > colors a blinking cow template image 1`] = `"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goFDRc7VmYGWwAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAALSURBVAjXY2AAAgAABQAB4iYFmwAAAABJRU5ErkJggg=="`;
4
+
3
5
  exports[`getCowImage > colors a cow template image 1`] = `"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goFDRc7VmYGWwAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAALSURBVAjXY2AAAgAABQAB4iYFmwAAAABJRU5ErkJggg=="`;
@@ -13,10 +13,24 @@ describe('getCowImage', () => {
13
13
  expect(image).toMatchSnapshot()
14
14
  })
15
15
 
16
+ test('colors a blinking cow template image', async () => {
17
+ const cow = generateCow({ color: cowColors.GREEN, id: '1' })
18
+ const image = await getCowImage(cow, { isBlinking: true })
19
+
20
+ expect(image).toMatchSnapshot()
21
+ })
22
+
16
23
  test('does not modify rainbow cow image', async () => {
17
24
  const cow = generateCow({ color: cowColors.RAINBOW })
18
25
  const image = await getCowImage(cow)
19
26
 
20
27
  expect(image).toEqual(animals.cow.rainbow)
21
28
  })
29
+
30
+ test('does not modify blinking rainbow cow image', async () => {
31
+ const cow = generateCow({ color: cowColors.RAINBOW })
32
+ const image = await getCowImage(cow, { isBlinking: true })
33
+
34
+ expect(image).toEqual(animals.cow.rainbowBlinking)
35
+ })
22
36
  })
@@ -37,8 +37,13 @@ const colorizeCowTemplate = (() => {
37
37
  * @param color
38
38
  * @returns Base64 representation of an image
39
39
  */
40
- return async (cowTemplate: string, color: cowColors) => {
41
- if (color === cowColors.RAINBOW) return animals.cow.rainbow
40
+ return async (
41
+ cowTemplate: string,
42
+ color: cowColors,
43
+ { isBlinking = false }: { isBlinking?: boolean } = {}
44
+ ) => {
45
+ if (color === cowColors.RAINBOW)
46
+ return isBlinking ? animals.cow.rainbowBlinking : animals.cow.rainbow
42
47
 
43
48
  const imageKey = `${color}_${cowTemplate}`
44
49
 
@@ -93,10 +98,19 @@ const colorizeCowTemplate = (() => {
93
98
  }
94
99
  })()
95
100
 
96
- export const getCowImage = async (cow: farmhand.cow): Promise<string> => {
101
+ export const getCowImage = async (
102
+ cow: farmhand.cow,
103
+ { isBlinking = false }: { isBlinking?: boolean } = {}
104
+ ): Promise<string> => {
97
105
  const cowIdNumber = convertStringToInteger(cow.id)
98
- const { variations } = animals.cow
99
- const cowTemplate = variations[cowIdNumber % variations.length]
100
106
 
101
- return await colorizeCowTemplate(cowTemplate, cow.color as cowColors)
107
+ const { variations, blinkingVariations } = animals.cow
108
+
109
+ const cowVariations = isBlinking ? blinkingVariations : variations
110
+
111
+ const cowTemplate = cowVariations[cowIdNumber % cowVariations.length]
112
+
113
+ return await colorizeCowTemplate(cowTemplate, cow.color as cowColors, {
114
+ isBlinking,
115
+ })
102
116
  }