@latticexyz/utils 0.9.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,187 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ # [0.9.0](https://github.com/latticexyz/mud/compare/v0.8.1...v0.9.0) (2022-09-13)
7
+
8
+ ### Bug Fixes
9
+
10
+ - **network:** align hex entity id formatting ([#140](https://github.com/latticexyz/mud/issues/140)) ([93b1bd6](https://github.com/latticexyz/mud/commit/93b1bd6688780dc185a1c7e353954e2c5c85f648))
11
+
12
+ ## [0.8.1](https://github.com/latticexyz/mud/compare/v0.8.0...v0.8.1) (2022-08-22)
13
+
14
+ **Note:** Version bump only for package @latticexyz/utils
15
+
16
+ # [0.8.0](https://github.com/latticexyz/mud/compare/v0.7.0...v0.8.0) (2022-08-22)
17
+
18
+ ### Features
19
+
20
+ - add mud.dev ([#133](https://github.com/latticexyz/mud/issues/133)) ([302588c](https://github.com/latticexyz/mud/commit/302588cbbab2803396b894bc006d13e6ac943da9))
21
+
22
+ # [0.7.0](https://github.com/latticexyz/mud/compare/v0.6.0...v0.7.0) (2022-08-19)
23
+
24
+ **Note:** Version bump only for package @latticexyz/utils
25
+
26
+ # [0.6.0](https://github.com/latticexyz/mud/compare/v0.5.1...v0.6.0) (2022-08-15)
27
+
28
+ ### Code Refactoring
29
+
30
+ - sync worker (+ integrated snapshot service) ([#125](https://github.com/latticexyz/mud/issues/125)) ([6173b59](https://github.com/latticexyz/mud/commit/6173b596713b0dad73d14288ece3ac66ca3972d3))
31
+
32
+ ### BREAKING CHANGES
33
+
34
+ - sync worker update stream returns component id instead of component key
35
+
36
+ - test(network): add tests for sync utils and SyncWorker logic
37
+
38
+ - chore: remove logs and improve comments
39
+
40
+ - chore: add logs
41
+
42
+ Co-authored-by: andrii dobroshynski <24281657+andriidski@users.noreply.github.com>
43
+
44
+ ## [0.5.1](https://github.com/latticexyz/mud/compare/v0.5.0...v0.5.1) (2022-08-05)
45
+
46
+ **Note:** Version bump only for package @latticexyz/utils
47
+
48
+ # [0.5.0](https://github.com/latticexyz/mud/compare/v0.4.3...v0.5.0) (2022-08-05)
49
+
50
+ ### Bug Fixes
51
+
52
+ - optimism, cancel action if gas check fails, add noise utils, fix ecs-browser entry point ([#119](https://github.com/latticexyz/mud/issues/119)) ([f35d3c3](https://github.com/latticexyz/mud/commit/f35d3c3cc7fc9385a215dfda6762a2a825c9fd6d))
53
+
54
+ ### Features
55
+
56
+ - logging library with support for topics/filters ([#123](https://github.com/latticexyz/mud/issues/123)) ([4eac3c6](https://github.com/latticexyz/mud/commit/4eac3c6f45cf300c683397d68e405001d31d8dda))
57
+
58
+ ## [0.4.3](https://github.com/latticexyz/mud/compare/v0.4.2...v0.4.3) (2022-07-30)
59
+
60
+ **Note:** Version bump only for package @latticexyz/utils
61
+
62
+ ## [0.4.2](https://github.com/latticexyz/mud/compare/v0.4.1...v0.4.2) (2022-07-29)
63
+
64
+ **Note:** Version bump only for package @latticexyz/utils
65
+
66
+ ## [0.4.1](https://github.com/latticexyz/mud/compare/v0.4.0...v0.4.1) (2022-07-29)
67
+
68
+ **Note:** Version bump only for package @latticexyz/utils
69
+
70
+ # [0.4.0](https://github.com/latticexyz/mud/compare/v0.3.2...v0.4.0) (2022-07-29)
71
+
72
+ ### Bug Fixes
73
+
74
+ - **cli:** extract encoded arguments from signature ([#116](https://github.com/latticexyz/mud/issues/116)) ([f630319](https://github.com/latticexyz/mud/commit/f6303194c5d7147a64542e43669fddebf3abad1a))
75
+
76
+ ### Features
77
+
78
+ - add 3d components ([d230339](https://github.com/latticexyz/mud/commit/d230339bdf3fbfaf4596de759a25fb616a7ab572))
79
+
80
+ ## [0.3.2](https://github.com/latticexyz/mud/compare/v0.3.1...v0.3.2) (2022-07-26)
81
+
82
+ **Note:** Version bump only for package @latticexyz/utils
83
+
84
+ ## [0.3.1](https://github.com/latticexyz/mud/compare/v0.3.0...v0.3.1) (2022-07-26)
85
+
86
+ **Note:** Version bump only for package @latticexyz/utils
87
+
88
+ # [0.3.0](https://github.com/latticexyz/mud/compare/v0.2.0...v0.3.0) (2022-07-26)
89
+
90
+ ### Features
91
+
92
+ - mudwar prototype (nyc sprint 2) ([#59](https://github.com/latticexyz/mud/issues/59)) ([a3db20e](https://github.com/latticexyz/mud/commit/a3db20e14c641b8b456775ee191eca6f016d47f5)), closes [#58](https://github.com/latticexyz/mud/issues/58) [#61](https://github.com/latticexyz/mud/issues/61) [#64](https://github.com/latticexyz/mud/issues/64) [#62](https://github.com/latticexyz/mud/issues/62) [#66](https://github.com/latticexyz/mud/issues/66) [#69](https://github.com/latticexyz/mud/issues/69) [#72](https://github.com/latticexyz/mud/issues/72) [#73](https://github.com/latticexyz/mud/issues/73) [#74](https://github.com/latticexyz/mud/issues/74) [#76](https://github.com/latticexyz/mud/issues/76) [#75](https://github.com/latticexyz/mud/issues/75) [#77](https://github.com/latticexyz/mud/issues/77) [#78](https://github.com/latticexyz/mud/issues/78) [#79](https://github.com/latticexyz/mud/issues/79) [#80](https://github.com/latticexyz/mud/issues/80) [#82](https://github.com/latticexyz/mud/issues/82) [#86](https://github.com/latticexyz/mud/issues/86) [#83](https://github.com/latticexyz/mud/issues/83) [#81](https://github.com/latticexyz/mud/issues/81) [#85](https://github.com/latticexyz/mud/issues/85) [#84](https://github.com/latticexyz/mud/issues/84) [#87](https://github.com/latticexyz/mud/issues/87) [#91](https://github.com/latticexyz/mud/issues/91) [#88](https://github.com/latticexyz/mud/issues/88) [#90](https://github.com/latticexyz/mud/issues/90) [#92](https://github.com/latticexyz/mud/issues/92) [#93](https://github.com/latticexyz/mud/issues/93) [#89](https://github.com/latticexyz/mud/issues/89) [#94](https://github.com/latticexyz/mud/issues/94) [#95](https://github.com/latticexyz/mud/issues/95) [#98](https://github.com/latticexyz/mud/issues/98) [#100](https://github.com/latticexyz/mud/issues/100) [#97](https://github.com/latticexyz/mud/issues/97) [#101](https://github.com/latticexyz/mud/issues/101) [#105](https://github.com/latticexyz/mud/issues/105) [#106](https://github.com/latticexyz/mud/issues/106)
93
+
94
+ # [0.2.0](https://github.com/latticexyz/mud/compare/v0.1.8...v0.2.0) (2022-07-05)
95
+
96
+ ### Features
97
+
98
+ - add webworker architecture for contract/client sync, add cache webworker ([#10](https://github.com/latticexyz/mud/issues/10)) ([4ef9f90](https://github.com/latticexyz/mud/commit/4ef9f909d1d3c10f6bea888b2c32b1d1df04185a)), closes [#14](https://github.com/latticexyz/mud/issues/14)
99
+ - on-chain maps (nyc sprint 1) ([#38](https://github.com/latticexyz/mud/issues/38)) ([089c46d](https://github.com/latticexyz/mud/commit/089c46d7c0e112d1670e3bcd01a35f08ee21d593)), closes [#17](https://github.com/latticexyz/mud/issues/17) [#20](https://github.com/latticexyz/mud/issues/20) [#18](https://github.com/latticexyz/mud/issues/18) [#25](https://github.com/latticexyz/mud/issues/25) [#26](https://github.com/latticexyz/mud/issues/26) [#27](https://github.com/latticexyz/mud/issues/27) [#28](https://github.com/latticexyz/mud/issues/28) [#29](https://github.com/latticexyz/mud/issues/29) [#30](https://github.com/latticexyz/mud/issues/30) [#31](https://github.com/latticexyz/mud/issues/31) [#33](https://github.com/latticexyz/mud/issues/33) [#32](https://github.com/latticexyz/mud/issues/32) [#34](https://github.com/latticexyz/mud/issues/34) [#35](https://github.com/latticexyz/mud/issues/35) [#36](https://github.com/latticexyz/mud/issues/36) [#37](https://github.com/latticexyz/mud/issues/37) [#39](https://github.com/latticexyz/mud/issues/39) [#40](https://github.com/latticexyz/mud/issues/40) [#41](https://github.com/latticexyz/mud/issues/41) [#42](https://github.com/latticexyz/mud/issues/42) [#43](https://github.com/latticexyz/mud/issues/43) [#44](https://github.com/latticexyz/mud/issues/44) [#45](https://github.com/latticexyz/mud/issues/45) [#46](https://github.com/latticexyz/mud/issues/46) [#48](https://github.com/latticexyz/mud/issues/48) [#49](https://github.com/latticexyz/mud/issues/49) [#50](https://github.com/latticexyz/mud/issues/50)
100
+
101
+ ### BREAKING CHANGES
102
+
103
+ - Components have to implement a getSchema() function
104
+
105
+ - feat(network): make Sync worker return a stream of ECS events (prev contract events)
106
+
107
+ - feat(ri-contracts): integrate solecs change (add getSchema to components)
108
+
109
+ - feat(ri-client): integrate network package changes
110
+
111
+ - feat(network): store ECS state in cache
112
+
113
+ - feat(network): load state from cache
114
+
115
+ - feat(utils): add more utils for iterables
116
+
117
+ - refactor(network): clean up
118
+
119
+ - feat(network): generalize component value decoder function, add tests
120
+
121
+ - fix(network): make it possible to subscribe to ecsStream from sync worker multiple times
122
+
123
+ - fix(network): start sync from provided initial block number
124
+
125
+ - feat(network): move storing ecs to indexDB to its own Cache worker
126
+
127
+ - feat(network): create separate cache for every World contract address
128
+
129
+ - fix(network): fix issues discovered during live review
130
+
131
+ - chore: remove unused import
132
+
133
+ - Update packages/network/src/createBlockNumberStream.ts
134
+
135
+ Co-authored-by: ludens <ludens@lattice.xyz>
136
+
137
+ - feat(network): add clock syncInterval as config parameter
138
+
139
+ - feat(utils): emit values through componentToStream and observableToStream only if non-null
140
+
141
+ - feat(network): add chain id to cache id, disable loading from cache on hardhat
142
+
143
+ - fix(contracts): change Position and EntityType schema to int32/uint32 to fit in js number
144
+
145
+ - docs(client): fix typos in comments
146
+
147
+ - fix(network): fix tests
148
+
149
+ - fix(scripting): integrate new network package into ri scripting
150
+
151
+ - fix(network): fix sending multiple requests for component schema if many events get reduced
152
+
153
+ ## [0.1.8](https://github.com/latticexyz/mud/compare/v0.1.7...v0.1.8) (2022-05-25)
154
+
155
+ **Note:** Version bump only for package @latticexyz/utils
156
+
157
+ ## [0.1.7](https://github.com/latticexyz/mud/compare/v0.1.6...v0.1.7) (2022-05-25)
158
+
159
+ **Note:** Version bump only for package @latticexyz/utils
160
+
161
+ ## [0.1.6](https://github.com/latticexyz/mud/compare/v0.1.5...v0.1.6) (2022-05-25)
162
+
163
+ **Note:** Version bump only for package @latticexyz/utils
164
+
165
+ ## [0.1.4](https://github.com/latticexyz/mud/compare/v0.1.3...v0.1.4) (2022-05-24)
166
+
167
+ **Note:** Version bump only for package @latticexyz/utils
168
+
169
+ ## [0.1.3](https://github.com/latticexyz/mud/compare/v0.1.2...v0.1.3) (2022-05-23)
170
+
171
+ **Note:** Version bump only for package @latticexyz/utils
172
+
173
+ ## [0.1.2](https://github.com/latticexyz/mud/compare/v0.1.1...v0.1.2) (2022-05-23)
174
+
175
+ **Note:** Version bump only for package @latticexyz/utils
176
+
177
+ ## [0.1.1](https://github.com/latticexyz/mud/compare/v0.1.0...v0.1.1) (2022-05-23)
178
+
179
+ **Note:** Version bump only for package @latticexyz/utils
180
+
181
+ # 0.1.0 (2022-05-23)
182
+
183
+ ### Features
184
+
185
+ - **@mud/utils:** add @mud/utils package ([fc721cc](https://github.com/latticexyz/mud/commit/fc721cc564b20150c3b13883cb3edb773f48e312))
186
+ - **@mud/utils:** add keccak256 hash function that accepts string inputs ([ca1a4e0](https://github.com/latticexyz/mud/commit/ca1a4e0cc7452724e703a6530c2e56112c307b66))
187
+ - **@mud/utils:** add stretch rxjs operator to add a minimum delay between events in a rxjs stream ([3a1673f](https://github.com/latticexyz/mud/commit/3a1673f5fba548f94afd5580a7e32007a6edd57f))
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # @latticexyz/utils
2
+
3
+ Useful utilities for everyday use
package/jest.config.js ADDED
@@ -0,0 +1,5 @@
1
+ /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
2
+ export default {
3
+ preset: "ts-jest",
4
+ testEnvironment: "node",
5
+ };
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@latticexyz/utils",
3
+ "license": "MIT",
4
+ "version": "0.9.0",
5
+ "type": "module",
6
+ "main": "src/index.ts",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/latticexyz/mud.git",
10
+ "directory": "packages/utils"
11
+ },
12
+ "scripts": {
13
+ "lint": "eslint . --ext .ts",
14
+ "test": "jest",
15
+ "build": "rimraf dist && rollup -c rollup.config.js",
16
+ "link": "yarn link",
17
+ "docs": "typedoc src"
18
+ },
19
+ "devDependencies": {
20
+ "@rollup/plugin-node-resolve": "^13.1.3",
21
+ "@rollup/plugin-typescript": "^8.3.1",
22
+ "@types/jest": "^27.4.1",
23
+ "ethers": "^5.6.6",
24
+ "jest": "^27.5.1",
25
+ "mobx": "^6.5.0",
26
+ "proxy-deep": "^3.1.1",
27
+ "rimraf": "^3.0.2",
28
+ "rollup": "^2.69.0",
29
+ "rollup-plugin-commonjs": "^10.1.0",
30
+ "rollup-plugin-peer-deps-external": "^2.2.4",
31
+ "rxjs": "^7.5.5",
32
+ "ts-jest": "^27.1.3",
33
+ "tslib": "^2.3.1",
34
+ "typedoc": "^0.23.10",
35
+ "typescript": "^4.5.5"
36
+ },
37
+ "peerDependencies": {
38
+ "ethers": "^5.6.6",
39
+ "mobx": "^6.5.0",
40
+ "proxy-deep": "^3.1.1",
41
+ "rxjs": "^7.5.5"
42
+ },
43
+ "gitHead": "40718ea9955e61196942d040189adec464500446"
44
+ }
@@ -0,0 +1,16 @@
1
+ import typescript from "@rollup/plugin-typescript";
2
+ import { nodeResolve } from "@rollup/plugin-node-resolve";
3
+ import commonjs from "rollup-plugin-commonjs";
4
+ import peerDepsExternal from "rollup-plugin-peer-deps-external";
5
+
6
+ import { defineConfig } from "rollup";
7
+
8
+ export default defineConfig({
9
+ input: "./src/index.ts",
10
+ treeshake: true,
11
+ output: {
12
+ dir: "dist",
13
+ sourcemap: true,
14
+ },
15
+ plugins: [nodeResolve(), typescript(), commonjs(), peerDepsExternal()],
16
+ });
@@ -0,0 +1,57 @@
1
+ import { coordToKey, keyToCoord } from "./CoordMap";
2
+
3
+ describe("CoordMap", () => {
4
+ describe("coordToKey", () => {
5
+ it("should be the inverse of keyToCoord", () => {
6
+ const MAX = 2 ** 15 - 1;
7
+ const coords = [
8
+ { x: 1, y: 2 },
9
+ { x: -1, y: 2 },
10
+ { x: 1, y: -2 },
11
+ { x: 0, y: 0 },
12
+ { x: -1, y: -2 },
13
+ { x: MAX, y: MAX },
14
+ { x: -1 * MAX, y: MAX },
15
+ { x: MAX, y: -1 * MAX },
16
+ { x: -1 * MAX, y: -1 * MAX },
17
+ ];
18
+
19
+ for (const coord of coords) {
20
+ const key = coordToKey(coord);
21
+ expect(keyToCoord(key)).toEqual(coord);
22
+ }
23
+ });
24
+ });
25
+
26
+ describe("keyToCoord", () => {
27
+ it("should be the inverse of coordToKey", () => {
28
+ const keys = [
29
+ "11111111111111110000000000000000",
30
+ "11011101110111011000101001001000",
31
+ "01101101101110110001010101111001",
32
+ "11010101111011010010010010001001",
33
+ "00111111111111110111000001001100",
34
+ "01101110001111010110010010001001",
35
+ "10101110011011010010010001010101",
36
+ "01011011101011010101100100101000",
37
+ "11011110111101111000010000100011",
38
+ "10110111011011010101101010001001",
39
+ "00110111011101110001000100010000",
40
+ "10110101101101010001001010001001",
41
+ "01100011010101111010010100110010",
42
+ "11111111111111111111111111111111",
43
+ "00000000000000000000000000000000",
44
+ ];
45
+
46
+ for (const key of keys) {
47
+ const numKey = parseInt(key, 2) >> 0;
48
+ const coord = keyToCoord(numKey);
49
+ expect(coordToKey(coord)).toEqual(numKey);
50
+ }
51
+ });
52
+
53
+ it("should work with {x: 0, y: 0}", () => {
54
+ expect(keyToCoord(0)).toEqual({ x: 0, y: 0 });
55
+ });
56
+ });
57
+ });
@@ -0,0 +1,106 @@
1
+ import { Coord } from "./types";
2
+ import { transformIterator } from "./iterable";
3
+
4
+ const LOWER_HALF_MASK = 2 ** 16 - 1;
5
+ const MAX_SUPPORTED = 2 ** 15 - 1;
6
+
7
+ export function subtract(from: CoordMap<boolean>, subtract: CoordMap<boolean>): CoordMap<boolean> {
8
+ const result = new CoordMap<boolean>();
9
+
10
+ for (const coord of from.coords()) {
11
+ if (subtract.get(coord)) continue;
12
+ result.set(coord, true);
13
+ }
14
+
15
+ return result;
16
+ }
17
+
18
+ export function coordToKey(coord: Coord) {
19
+ const key = (coord.x << 16) | (coord.y & LOWER_HALF_MASK);
20
+ return key;
21
+
22
+ // Old version using strings:
23
+ // return `${coord.x}/${coord.y}`;
24
+ }
25
+
26
+ export function keyToCoord(key: number): Coord {
27
+ const x = key >> 16;
28
+ const y = (key << 16) >> 16;
29
+ return { x, y };
30
+
31
+ // Old version using strings:
32
+ // const fragments = key.split("/");
33
+ // return { x: Number(fragments[0]), y: Number(fragments[1]) };
34
+ }
35
+
36
+ export class CoordMap<T> {
37
+ map: Map<number, T>;
38
+ defaultValue?: T;
39
+
40
+ constructor(props?: { defaultValue?: T }) {
41
+ this.map = new Map<number, T>();
42
+ this.defaultValue = props?.defaultValue;
43
+ }
44
+
45
+ static from<T>(coordMapLike: { map: Map<number, T>; defaultValue?: T }): CoordMap<T> {
46
+ const coordMap = new CoordMap<T>();
47
+ coordMap.map = coordMapLike.map;
48
+ coordMap.defaultValue = coordMapLike.defaultValue;
49
+ return coordMap;
50
+ }
51
+
52
+ set(coord: Coord, value: T) {
53
+ if (
54
+ coord.x > MAX_SUPPORTED ||
55
+ coord.x < -1 * MAX_SUPPORTED ||
56
+ coord.y > MAX_SUPPORTED ||
57
+ coord.y < -1 * MAX_SUPPORTED
58
+ ) {
59
+ throw new Error(`CoordMap only supports coords up to ${MAX_SUPPORTED}`);
60
+ }
61
+ return this.map.set(coordToKey(coord), value);
62
+ }
63
+
64
+ get(coord: Coord) {
65
+ return this.map.get(coordToKey(coord)) ?? this.defaultValue;
66
+ }
67
+
68
+ keys() {
69
+ return this.map.keys();
70
+ }
71
+
72
+ coords(): IterableIterator<Coord> {
73
+ return transformIterator(this.map.keys(), (key) => keyToCoord(key));
74
+ }
75
+
76
+ entries() {
77
+ return this.map.entries();
78
+ }
79
+
80
+ toArray(): [Coord, T][] {
81
+ const entries = Array.from(this.map.entries());
82
+ return entries.map(([key, value]) => [keyToCoord(key), value]);
83
+ }
84
+
85
+ values() {
86
+ return this.map.values();
87
+ }
88
+
89
+ delete(coord: Coord) {
90
+ return this.map.delete(coordToKey(coord));
91
+ }
92
+
93
+ has(coord: Coord): boolean {
94
+ return this.map.has(coordToKey(coord));
95
+ }
96
+
97
+ clear() {
98
+ for (const key of this.map.keys()) {
99
+ this.map.delete(key);
100
+ }
101
+ }
102
+
103
+ get size(): number {
104
+ return this.map.size;
105
+ }
106
+ }
package/src/area.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { Area, Coord } from "./types";
2
+
3
+ export function areaContains(area: Area, coord: Coord) {
4
+ return coord.x >= area.x && coord.y >= area.y && coord.x < area.x + area.width && coord.y < area.y + area.height;
5
+ }
6
+
7
+ export function coordsOf(area: Area) {
8
+ const coords: Coord[] = [];
9
+ for (let dx = 0; dx < area.width; dx++) {
10
+ for (let dy = 0; dy < area.height; dy++) {
11
+ coords.push({ x: area.x + dx, y: area.y + dy });
12
+ }
13
+ }
14
+ return coords;
15
+ }
package/src/arrays.ts ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * TypeScript type guard to assert the type of a non-empty array
3
+ * @param array Any array to check for non-emptiness
4
+ * @returns True if the empty is non-empty, else false. TypeScript accepts the array as non-empty after the assertion.
5
+ */
6
+ export function isNotEmpty<T>(array: T[]): array is [T, ...T[]] {
7
+ if (array.length === 0) return false;
8
+ return true;
9
+ }
10
+
11
+ /**
12
+ * Filters undefined values from an array and lets TypeScript know the resulting array
13
+ * does not have undefined values
14
+ * @param array Array potentially including undefined values
15
+ * @returns Array without undefined values
16
+ */
17
+ export function filterNullishValues<T>(array: (T | undefined)[]): T[] {
18
+ return array.filter((value) => value != null) as T[];
19
+ }
package/src/console.ts ADDED
@@ -0,0 +1,62 @@
1
+ const TOPICS_KEY = "mud-logger-topics";
2
+
3
+ export function enableLogger() {
4
+ const windowConsole = window.console;
5
+ let filtersActive = Boolean(localStorage.getItem(TOPICS_KEY));
6
+
7
+ const topicsString = localStorage.getItem(TOPICS_KEY);
8
+ let topics: string[] = topicsString ? JSON.parse(topicsString) : [];
9
+
10
+ function log(...logs: string[]) {
11
+ if (filtersActive) return;
12
+ windowConsole.log(...logs);
13
+ }
14
+
15
+ function logWithTopic(topic: string, ...logs: string[]) {
16
+ if (!filtersActive || topics.includes(topic)) {
17
+ windowConsole.log(`--- BETTER CONSOLE / TOPIC ${topic} ---`);
18
+ windowConsole.log(...logs);
19
+ }
20
+ }
21
+
22
+ function enableFilters() {
23
+ localStorage.setItem(TOPICS_KEY, JSON.stringify([]));
24
+ filtersActive = true;
25
+ }
26
+
27
+ function disableFilters() {
28
+ localStorage.removeItem(TOPICS_KEY);
29
+ filtersActive = false;
30
+ }
31
+
32
+ function addTopic(topic: string) {
33
+ topics.push(topic);
34
+ localStorage.setItem(TOPICS_KEY, JSON.stringify(topics));
35
+ }
36
+
37
+ function removeTopic(topic: string) {
38
+ topics = topics.filter((t) => t !== topic);
39
+ localStorage.setItem(TOPICS_KEY, JSON.stringify(topics));
40
+ }
41
+
42
+ function resetTopics() {
43
+ topics = [];
44
+ localStorage.setItem(TOPICS_KEY, JSON.stringify(topics));
45
+ }
46
+
47
+ const logger = {
48
+ ...windowConsole,
49
+ log,
50
+ logWithTopic,
51
+ enableFilters,
52
+ disableFilters,
53
+ addTopic,
54
+ removeTopic,
55
+ resetTopics,
56
+ };
57
+
58
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
59
+ (window as any).logger = logger;
60
+ window.console = logger;
61
+ return logger;
62
+ }
@@ -0,0 +1,14 @@
1
+ import { cubicNoiseSample2, cubicNoiseConfig } from "./cubic";
2
+
3
+ describe("Cubic", () => {
4
+ it("computes noise", () => {
5
+ const coords: [number, number][] = [];
6
+ for (let i = 0; i < 100; i++) {
7
+ coords.push([Math.floor((Math.random() - 0.5) * 1000), Math.floor((Math.random() - 0.5) * 1000)]);
8
+ }
9
+
10
+ const noises = coords.map((c) => cubicNoiseSample2(cubicNoiseConfig(1000, 64, 16, 256, 256), c[0], c[1]));
11
+ console.log("coords", JSON.stringify(coords));
12
+ console.log("noises", JSON.stringify(noises));
13
+ });
14
+ });
package/src/cubic.ts ADDED
@@ -0,0 +1,109 @@
1
+ const RND_A = 134775813;
2
+ const RND_B = 1103515245;
3
+ const ACCURACY = 1000;
4
+
5
+ export function randomize(seed: number, x: number, y: number) {
6
+ return (((((x ^ y) * RND_A) ^ (seed + x)) * (((RND_B * x) << 16) ^ (RND_B * y - RND_A))) >>> 0) / 4294967295;
7
+ }
8
+
9
+ export function tile(coordinate: number, period: number) {
10
+ if (coordinate < 0) while (coordinate < 0) coordinate += period;
11
+ return coordinate % period;
12
+ }
13
+
14
+ export function interpolate(a: number, b: number, c: number, d: number, x: number, s: number, scale: number) {
15
+ const p = d - c - (a - b);
16
+ return (b * Math.pow(s, 3) + x * (c * Math.pow(s, 2) + a * s * (-s + x) + x * (-(b + p) * s + p * x))) * scale;
17
+
18
+ // return (x) * ((x ) * ((x ) * p + (a - b - p)) + (c - a)) + b;
19
+ }
20
+
21
+ /**
22
+ * Config a cubic noise.
23
+ * @param {Number} seed A seed in the range [0, 1].
24
+ * @param {Number} [periodX] The number of units after which the x coordinate repeats.
25
+ * @param {Number} [periodY] The number of units after which the y coordinate repeats.
26
+ * @returns {Object} A configuration object used by noise functions.
27
+ */
28
+ export function cubicNoiseConfig(
29
+ seed: number,
30
+ octave: number,
31
+ scale: number,
32
+ periodX = Number.MAX_SAFE_INTEGER,
33
+ periodY = Number.MAX_SAFE_INTEGER
34
+ ) {
35
+ return {
36
+ seed: Math.floor(seed * Number.MAX_SAFE_INTEGER),
37
+ periodX: periodX,
38
+ periodY: periodY,
39
+ octave,
40
+ scale,
41
+ };
42
+ }
43
+
44
+ /**
45
+ * Sample 1D cubic noise.
46
+ * @param {Object} config A valid noise configuration.
47
+ * @param {Number} x The X position to sample at.
48
+ * @returns {Number} A noise value in the range [0, 1].
49
+ */
50
+ export function cubicNoiseSample1(config: ReturnType<typeof cubicNoiseConfig>, x: number) {
51
+ const xi = Math.floor(x);
52
+ const lerp = x - xi;
53
+
54
+ return (
55
+ interpolate(
56
+ randomize(config.seed, tile(xi - 1, config.periodX), 0),
57
+ randomize(config.seed, tile(xi, config.periodX), 0),
58
+ randomize(config.seed, tile(xi + 1, config.periodX), 0),
59
+ randomize(config.seed, tile(xi + 2, config.periodX), 0),
60
+ lerp,
61
+ 1,
62
+ 1
63
+ ) *
64
+ 0.666666 +
65
+ 0.166666
66
+ );
67
+ }
68
+
69
+ /**
70
+ * Sample 2D cubic noise.
71
+ * @param {Object} config A valid noise configuration.
72
+ * @param {Number} x The X position to sample at.
73
+ * @param {Number} y The Y position to sample at.
74
+ * @returns {Number} A noise value in the range [0, 1].
75
+ */
76
+ export function cubicNoiseSample2(
77
+ { octave, periodX, periodY, seed, scale }: ReturnType<typeof cubicNoiseConfig>,
78
+ x: number,
79
+ y: number
80
+ ) {
81
+ const xi = Math.floor(x / octave);
82
+ const lerpX = Math.floor((x * ACCURACY) / octave) - xi * ACCURACY;
83
+ const yi = Math.floor(y / octave);
84
+ const lerpY = Math.floor((y * ACCURACY) / octave) - yi * ACCURACY;
85
+ const x0 = tile(xi - 1, periodX);
86
+ const x1 = tile(xi, periodX);
87
+ const x2 = tile(xi + 1, periodX);
88
+ const x3 = tile(xi + 2, periodX);
89
+
90
+ const xSamples = new Array(4);
91
+
92
+ for (let i = 0; i < 4; ++i) {
93
+ const y = tile(yi - 1 + i, periodY);
94
+
95
+ xSamples[i] = interpolate(
96
+ randomize(seed, x0, y),
97
+ randomize(seed, x1, y),
98
+ randomize(seed, x2, y),
99
+ randomize(seed, x3, y),
100
+ lerpX,
101
+ ACCURACY,
102
+ 1
103
+ );
104
+ }
105
+
106
+ return Math.floor(
107
+ interpolate(xSamples[0], xSamples[1], xSamples[2], xSamples[3], lerpY, ACCURACY, scale) / Math.pow(ACCURACY, 6)
108
+ );
109
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * A convenient way to create a promise with resolve and reject functions.
3
+ * @returns Tuple with resolve function, reject function and promise.
4
+ */
5
+ export function deferred<T>(): [(t: T) => void, (t: Error) => void, Promise<T>] {
6
+ let resolve: ((t: T) => void) | null = null;
7
+ let reject: ((t: Error) => void) | null = null;
8
+ const promise = new Promise<T>((r, rj) => {
9
+ resolve = (t: T) => r(t);
10
+ reject = (e: Error) => rj(e);
11
+ });
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ return [resolve as any, reject as any, promise];
14
+ }