mcbe-leveldb 1.11.0-jsonly → 1.12.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 +7 -0
- package/DBUtils.ts +246 -0
- package/LevelUtils.d.ts +40 -1
- package/LevelUtils.js +55 -0
- package/LevelUtils.js.map +1 -1
- package/LevelUtils.ts +3660 -0
- package/SNBTUtils.ts +2146 -0
- package/__biome_data__.ts +282 -0
- package/index.ts +14 -0
- package/nbtSchemas.d.ts +12 -0
- package/nbtSchemas.js +14 -0
- package/nbtSchemas.js.map +1 -1
- package/nbtSchemas.ts +25644 -0
- package/package.json +2 -2
- package/utils/JSONB.ts +566 -0
package/Changelog.md
CHANGED
package/DBUtils.ts
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import type { LevelDB } from "@8crafter/leveldb-zlib";
|
|
2
|
+
import { getContentTypeFromDBKey, type DBEntryContentType } from "./LevelUtils.ts";
|
|
3
|
+
import NBT from "prismarine-nbt";
|
|
4
|
+
import { JSONB } from "./utils/JSONB.ts";
|
|
5
|
+
|
|
6
|
+
// TO-DO: Make an abstract class version of the LevelDB class to use as the type of the db parameter.
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Gets the keys from the LevelDB with a specific content type.
|
|
10
|
+
*
|
|
11
|
+
* @template T The content type to look for.
|
|
12
|
+
* @param db The LevelDB. Should match the type of the {@link LevelDB} class from the {@link https://www.npmjs.com/package/@8crafter/leveldb-zlib | @8crafter/leveldb-zlib} package. It does not have to be the one from that package, as long as the types match.
|
|
13
|
+
* @param type The {@link DBEntryContentType | content type} to look for.
|
|
14
|
+
* @returns The keys from the LevelDB with the specified content type, the keys are in Buffer format, this is because some keys contain binary data like chunk indices.
|
|
15
|
+
*/
|
|
16
|
+
export async function getKeysOfType<T extends DBEntryContentType>(db: LevelDB, type: T): Promise<Buffer<ArrayBuffer>[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Gets the keys from the list of LevelDB keys with a specific content type.
|
|
19
|
+
*
|
|
20
|
+
* @template T The content type to look for.
|
|
21
|
+
* @template TArrayBuffer The type of the buffers.
|
|
22
|
+
* @param dbKeys The LevelDB keys. Should be an array of Buffers.
|
|
23
|
+
* @param type The {@link DBEntryContentType | content type} to look for.
|
|
24
|
+
* @returns The keys from the provided LevelDB keys array with the specified content type, the keys are in Buffer format, this is because some keys contain binary data like chunk indices.
|
|
25
|
+
*/
|
|
26
|
+
export function getKeysOfType<T extends DBEntryContentType, TArrayBuffer extends ArrayBufferLike = ArrayBufferLike>(
|
|
27
|
+
dbKeys: Buffer<TArrayBuffer>[],
|
|
28
|
+
type: T
|
|
29
|
+
): Buffer<TArrayBuffer>[];
|
|
30
|
+
export function getKeysOfType<T extends DBEntryContentType>(dbOrDBKeys: LevelDB | Buffer[], type: T): Promise<Buffer<ArrayBuffer>[]> | Buffer[] {
|
|
31
|
+
if (Array.isArray(dbOrDBKeys)) return dbOrDBKeys.filter((key: Buffer): boolean => getContentTypeFromDBKey(key) === type);
|
|
32
|
+
return new Promise(
|
|
33
|
+
(resolve: (value: Buffer<ArrayBuffer>[]) => void): void =>
|
|
34
|
+
void (async (): Promise<void> => {
|
|
35
|
+
const foundKeys: Buffer<ArrayBuffer>[] = [];
|
|
36
|
+
for await (const [rawKey, _value] of dbOrDBKeys.getIterator({ keys: true, keyAsBuffer: true, values: false })) {
|
|
37
|
+
if (getContentTypeFromDBKey(rawKey) === type) foundKeys.push(rawKey);
|
|
38
|
+
}
|
|
39
|
+
resolve(foundKeys);
|
|
40
|
+
})()
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Gets the keys from the LevelDB with one of the specified content types.
|
|
46
|
+
*
|
|
47
|
+
* @template T The content types to look for.
|
|
48
|
+
* @param db The LevelDB. Should match the type of the {@link LevelDB} class from the {@link https://www.npmjs.com/package/@8crafter/leveldb-zlib | @8crafter/leveldb-zlib} package. It does not have to be the one from that package, as long as the types match.
|
|
49
|
+
* @param types The {@link DBEntryContentType | content types} to look for.
|
|
50
|
+
* @returns An object mapping each of the specified content types to the keys from the LevelDB with that content type, the keys are in Buffer format, this is because some keys contain binary data like chunk indices.
|
|
51
|
+
*/
|
|
52
|
+
export async function getKeysOfTypes<T extends DBEntryContentType[] | readonly DBEntryContentType[]>(
|
|
53
|
+
db: LevelDB,
|
|
54
|
+
types: T
|
|
55
|
+
): Promise<{ [key in T[number]]: Buffer<ArrayBuffer>[] }>;
|
|
56
|
+
/**
|
|
57
|
+
* Gets the keys from the list of LevelDB keys with one of the specified content types.
|
|
58
|
+
*
|
|
59
|
+
* @template T The content types to look for.
|
|
60
|
+
* @template TArrayBuffer The type of the buffers.
|
|
61
|
+
* @param dbKeys The LevelDB keys. Should be an array of Buffers.
|
|
62
|
+
* @param types The {@link DBEntryContentType | content types} to look for.
|
|
63
|
+
* @returns An object mapping each of the specified content types to the keys from the provided LevelDB keys array with that content type, the keys are in Buffer format, this is because some keys contain binary data like chunk indices.
|
|
64
|
+
*/
|
|
65
|
+
export function getKeysOfTypes<T extends DBEntryContentType[] | readonly DBEntryContentType[], TArrayBuffer extends ArrayBufferLike>(
|
|
66
|
+
dbKeys: Buffer<TArrayBuffer>[],
|
|
67
|
+
types: T
|
|
68
|
+
): { [key in T[number]]: Buffer<TArrayBuffer>[] };
|
|
69
|
+
export function getKeysOfTypes<T extends DBEntryContentType[] | readonly DBEntryContentType[]>(
|
|
70
|
+
dbOrDBKeys: LevelDB | Buffer[],
|
|
71
|
+
types: T
|
|
72
|
+
): Promise<{ [key in T[number]]: Buffer<ArrayBuffer>[] }> | { [key in T[number]]: Buffer[] } {
|
|
73
|
+
const results = {} as { [key in T[number]]: Buffer<any>[] };
|
|
74
|
+
types.forEach((contentType: T[number]): void => {
|
|
75
|
+
results[contentType] = [];
|
|
76
|
+
});
|
|
77
|
+
if (Array.isArray(dbOrDBKeys)) {
|
|
78
|
+
for (const key of dbOrDBKeys) {
|
|
79
|
+
const contentType: DBEntryContentType = getContentTypeFromDBKey(key);
|
|
80
|
+
if (types.includes(contentType)) results[contentType as T[number]].push(key);
|
|
81
|
+
}
|
|
82
|
+
return results;
|
|
83
|
+
}
|
|
84
|
+
return new Promise(
|
|
85
|
+
(resolve: (value: { [key in T[number]]: Buffer<ArrayBuffer>[] }) => void): void =>
|
|
86
|
+
void (async (): Promise<void> => {
|
|
87
|
+
for await (const [rawKey, _value] of dbOrDBKeys.getIterator({ keys: true, keyAsBuffer: true, values: false })) {
|
|
88
|
+
const contentType: DBEntryContentType = getContentTypeFromDBKey(rawKey);
|
|
89
|
+
if (types.includes(contentType)) results[contentType as T[number]].push(rawKey);
|
|
90
|
+
}
|
|
91
|
+
resolve(results);
|
|
92
|
+
})()
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Gets the keys from the LevelDB with one of the specified content types.
|
|
98
|
+
*
|
|
99
|
+
* @template T The content types to look for.
|
|
100
|
+
* @param db The LevelDB. Should match the type of the {@link LevelDB} class from the {@link https://www.npmjs.com/package/@8crafter/leveldb-zlib | @8crafter/leveldb-zlib} package. It does not have to be the one from that package, as long as the types match.
|
|
101
|
+
* @param types The {@link DBEntryContentType | content types} to look for.
|
|
102
|
+
* @returns An object mapping each of the specified content types to the keys from the LevelDB with that content type, the keys are in Buffer format, this is because some keys contain binary data like chunk indices.
|
|
103
|
+
*/
|
|
104
|
+
export function getKeysOfTypesG<T extends DBEntryContentType[] | readonly DBEntryContentType[]>(
|
|
105
|
+
db: LevelDB,
|
|
106
|
+
types: T
|
|
107
|
+
): AsyncGenerator<{ count: number; results: { [key in T[number]]: Buffer<ArrayBuffer>[] } }, { [key in T[number]]: Buffer<ArrayBuffer>[] }>;
|
|
108
|
+
/**
|
|
109
|
+
* Gets the keys from the list of LevelDB keys with one of the specified content types.
|
|
110
|
+
*
|
|
111
|
+
* @template T The content types to look for.
|
|
112
|
+
* @template TArrayBuffer The type of the buffers.
|
|
113
|
+
* @param dbKeys The LevelDB keys. Should be an array of Buffers.
|
|
114
|
+
* @param types The {@link DBEntryContentType | content types} to look for.
|
|
115
|
+
* @returns An object mapping each of the specified content types to the keys from the provided LevelDB keys array with that content type, the keys are in Buffer format, this is because some keys contain binary data like chunk indices.
|
|
116
|
+
*/
|
|
117
|
+
export function getKeysOfTypesG<T extends DBEntryContentType[] | readonly DBEntryContentType[], TArrayBuffer extends ArrayBufferLike>(
|
|
118
|
+
dbKeys: Buffer<TArrayBuffer>[],
|
|
119
|
+
types: T
|
|
120
|
+
): Generator<{ count: number; results: { [key in T[number]]: Buffer<TArrayBuffer>[] } }, { [key in T[number]]: Buffer<TArrayBuffer>[] }>;
|
|
121
|
+
export function getKeysOfTypesG<T extends DBEntryContentType[] | readonly DBEntryContentType[]>(
|
|
122
|
+
dbOrDBKeys: LevelDB | Buffer[],
|
|
123
|
+
types: T
|
|
124
|
+
):
|
|
125
|
+
| AsyncGenerator<{ count: number; results: { [key in T[number]]: Buffer<ArrayBuffer>[] } }, { [key in T[number]]: Buffer<ArrayBuffer>[] }>
|
|
126
|
+
| Generator<{ count: number; results: { [key in T[number]]: Buffer<ArrayBuffer>[] } }, { [key in T[number]]: Buffer[] }> {
|
|
127
|
+
const results = {} as { [key in T[number]]: Buffer<any>[] };
|
|
128
|
+
var count = 0;
|
|
129
|
+
types.forEach((contentType: T[number]): void => {
|
|
130
|
+
results[contentType] = [];
|
|
131
|
+
});
|
|
132
|
+
if (Array.isArray(dbOrDBKeys)) {
|
|
133
|
+
return (function* getKeysOfTypesGInner() {
|
|
134
|
+
for (const key of dbOrDBKeys) {
|
|
135
|
+
const contentType: DBEntryContentType = getContentTypeFromDBKey(key);
|
|
136
|
+
if (types.includes(contentType)) {
|
|
137
|
+
results[contentType as T[number]].push(key);
|
|
138
|
+
count++;
|
|
139
|
+
}
|
|
140
|
+
yield { count, results };
|
|
141
|
+
}
|
|
142
|
+
return results;
|
|
143
|
+
})();
|
|
144
|
+
}
|
|
145
|
+
return (async function* getKeysOfTypesGInner() {
|
|
146
|
+
for await (const [rawKey, _value] of dbOrDBKeys.getIterator({ keys: true, keyAsBuffer: true, values: false })) {
|
|
147
|
+
const contentType: DBEntryContentType = getContentTypeFromDBKey(rawKey);
|
|
148
|
+
if (types.includes(contentType)) {
|
|
149
|
+
results[contentType as T[number]].push(rawKey);
|
|
150
|
+
count++;
|
|
151
|
+
}
|
|
152
|
+
yield { count, results };
|
|
153
|
+
}
|
|
154
|
+
return results;
|
|
155
|
+
})();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Gets a player's name from their UUID.
|
|
160
|
+
*
|
|
161
|
+
* Only works if the player's name was stored in an add-on's dynamic properties with their ID linked to it, and it only works for a hardcoded list of add-ons,
|
|
162
|
+
* if you have your own add-on that you would like this to be able to read the player's names from, {@link https://www.8crafter.com/main/contact | contact 8Crafter},
|
|
163
|
+
* or make a pull request.
|
|
164
|
+
*
|
|
165
|
+
* @param db The LevelDB. Should match the type of the {@link LevelDB} class from the {@link https://www.npmjs.com/package/@8crafter/leveldb-zlib | @8crafter/leveldb-zlib} package. It does not have to be the one from that package, as long as the types match.
|
|
166
|
+
* @param uuid The UUID of the play to get the name of.
|
|
167
|
+
* @returns The name of the player, or `null` if the player's name cannot be found or the world has no dynamic properties.
|
|
168
|
+
*
|
|
169
|
+
* @throws {any} If there was an error reading the DynamicProperties from the DB.
|
|
170
|
+
*/
|
|
171
|
+
export async function getPlayerNameFromUUID(db: LevelDB, uuid: string | bigint): Promise<string | null> {
|
|
172
|
+
const dynamicProperties: NBT.NBT | null = await db
|
|
173
|
+
.get("DynamicProperties")
|
|
174
|
+
.then((data: Buffer | null): Promise<NBT.NBT> | null =>
|
|
175
|
+
data ? NBT.parse(data!).then((data: { parsed: NBT.NBT; type: NBT.NBTFormat; metadata: NBT.Metadata }): NBT.NBT => data.parsed) : null
|
|
176
|
+
);
|
|
177
|
+
if (!dynamicProperties) return null;
|
|
178
|
+
return getPlayerNameFromUUIDSync(dynamicProperties, uuid);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Gets a player's name from their UUID using the provided dynamic properties data.
|
|
183
|
+
*
|
|
184
|
+
* Only works if the player's name was stored in an add-on's dynamic properties with their ID linked to it, and it only works for a hardcoded list of add-ons,
|
|
185
|
+
* if you have your own add-on that you would like this to be able to read the player's names from, {@link https://www.8crafter.com/main/contact | contact 8Crafter},
|
|
186
|
+
* or make a pull request.
|
|
187
|
+
*
|
|
188
|
+
* @param dynamicProperties The dynamic properties data, should be the data from the `DynamicProperties` LevelDB key.
|
|
189
|
+
* @param uuid The UUID of the play to get the name of.
|
|
190
|
+
* @returns The name of the player, or `null` if the player's name cannot be found .
|
|
191
|
+
*/
|
|
192
|
+
export function getPlayerNameFromUUIDSync(dynamicProperties: NBT.NBT, uuid: string | bigint): string | null {
|
|
193
|
+
const UUIDString: string = uuid.toString();
|
|
194
|
+
for (const parser of playerUUIDToNameDynamicPropertyParsers) {
|
|
195
|
+
const name: string | null = parser(dynamicProperties, UUIDString);
|
|
196
|
+
if (name !== null) return name;
|
|
197
|
+
}
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* A function that can be used to get a player's name from their UUID from the dynamic properties.
|
|
203
|
+
*/
|
|
204
|
+
interface PlayerUUIDToNameDynamicPropertyParser {
|
|
205
|
+
/**
|
|
206
|
+
* A function that can be used to get a player's name from their UUID from the dynamic properties.
|
|
207
|
+
*
|
|
208
|
+
* @param dynamicProperties The dynamic properties data, should be the data from the `DynamicProperties` LevelDB key.
|
|
209
|
+
* @param uuid The UUID of the player to get the name of.
|
|
210
|
+
* @returns The name of the player, or `null` if the player's name cannot be found.
|
|
211
|
+
*/
|
|
212
|
+
(dynamicProperties: NBT.NBT, uuid: string): string | null;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* The list of functions that can be used to get a player's name from their UUID from the dynamic properties.
|
|
217
|
+
*
|
|
218
|
+
* These will be called in order until one of them returns a non-null value.
|
|
219
|
+
*/
|
|
220
|
+
const playerUUIDToNameDynamicPropertyParsers: PlayerUUIDToNameDynamicPropertyParser[] = [
|
|
221
|
+
function parse8CraftersServerUtilities(dynamicProperties: NBT.NBT, uuid: string): string | null {
|
|
222
|
+
const addOnUUIDs: string[] = [
|
|
223
|
+
// Internal development version
|
|
224
|
+
"53170125-3e79-4659-9bba-e49eb90b6ded",
|
|
225
|
+
// Release version
|
|
226
|
+
"53170125-3e79-4659-9bba-e49eb90b6dea",
|
|
227
|
+
];
|
|
228
|
+
for (const addOnUUID of addOnUUIDs) {
|
|
229
|
+
const addonDynamicProperties: NBT.Compound["value"] | null =
|
|
230
|
+
dynamicProperties.value[addOnUUID]?.type === "compound" ? dynamicProperties.value[addOnUUID].value : null;
|
|
231
|
+
if (!addonDynamicProperties) continue;
|
|
232
|
+
for (const key in addonDynamicProperties) {
|
|
233
|
+
if (key !== `player:${uuid}`) continue;
|
|
234
|
+
const dynamicPropertyValue: NBT.Byte | NBT.Double | NBT.String | NBT.List<NBT.TagType.Float> = addonDynamicProperties[key]! as any;
|
|
235
|
+
if (dynamicPropertyValue.type !== "string") continue;
|
|
236
|
+
try {
|
|
237
|
+
const data: any = JSONB.parse(dynamicPropertyValue.value);
|
|
238
|
+
if (typeof data === "object" && data !== null && typeof data.name === "string") return data.name;
|
|
239
|
+
} catch (e) {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return null;
|
|
245
|
+
},
|
|
246
|
+
];
|
package/LevelUtils.d.ts
CHANGED
|
@@ -43,7 +43,7 @@ export declare const gameModes: readonly ["survival", "creative", "adventure", u
|
|
|
43
43
|
/**
|
|
44
44
|
* The content types for LevelDB entries.
|
|
45
45
|
*/
|
|
46
|
-
export declare const DBEntryContentTypes: readonly ["Data3D", "Version", "Data2D", "Data2DLegacy", "SubChunkPrefix", "LegacyTerrain", "BlockEntity", "Entity", "PendingTicks", "LegacyBlockExtraData", "BiomeState", "FinalizedState", "ConversionData", "BorderBlocks", "HardcodedSpawners", "RandomTicks", "Checksums", "GenerationSeed", "GeneratedPreCavesAndCliffsBlending", "BlendingBiomeHeight", "MetaDataHash", "BlendingData", "ActorDigestVersion", "LegacyVersion", "AABBVolumes", "VillageDwellers", "VillageInfo", "VillagePOI", "VillagePlayers", "VillageRaid", "Player", "PlayerClient", "ActorPrefix", "ChunkLoadedRequest", "Digest", "Map", "Portals", "SchedulerWT", "StructureTemplate", "TickingArea", "FlatWorldLayers", "LegacyOverworld", "LegacyNether", "LegacyTheEnd", "MVillages", "Villages", "LevelSpawnWasFixed", "PositionTrackingDB", "PositionTrackingLastId", "Scoreboard", "Overworld", "Nether", "TheEnd", "AutonomousEntities", "BiomeData", "BiomeIdsTable", "MobEvents", "DynamicProperties", "LevelChunkMetaDataDictionary", "RealmsStoriesData", "LevelDat", "ForcedWorldCorruption", "Unknown"];
|
|
46
|
+
export declare const DBEntryContentTypes: readonly ["Data3D", "Version", "Data2D", "Data2DLegacy", "SubChunkPrefix", "LegacyTerrain", "BlockEntity", "Entity", "PendingTicks", "LegacyBlockExtraData", "BiomeState", "FinalizedState", "ConversionData", "BorderBlocks", "HardcodedSpawners", "RandomTicks", "Checksums", "GenerationSeed", "GeneratedPreCavesAndCliffsBlending", "BlendingBiomeHeight", "MetaDataHash", "BlendingData", "ActorDigestVersion", "LegacyVersion", "AABBVolumes", "VillageDwellers", "VillageInfo", "VillagePOI", "VillagePlayers", "VillageRaid", "Player", "PlayerClient", "ActorPrefix", "ChunkLoadedRequest", "Digest", "Map", "Portals", "SchedulerWT", "StructureTemplate", "TickingArea", "FlatWorldLayers", "LegacyOverworld", "LegacyNether", "LegacyTheEnd", "MVillages", "Villages", "LevelSpawnWasFixed", "PositionTrackingDB", "PositionTrackingLastId", "Scoreboard", "Overworld", "Nether", "TheEnd", "AutonomousEntities", "BiomeData", "BiomeIdsTable", "MobEvents", "DynamicProperties", "LevelChunkMetaDataDictionary", "RealmsStoriesData", "LevelDat", "WorldClocks", "ForcedWorldCorruption", "Unknown"];
|
|
47
47
|
/**
|
|
48
48
|
* Maps content types to grouping labels.
|
|
49
49
|
*
|
|
@@ -111,6 +111,7 @@ export declare const DBEntryContentTypesGrouping: {
|
|
|
111
111
|
readonly LevelChunkMetaDataDictionary: "LevelChunkMetaDataDictionary";
|
|
112
112
|
readonly RealmsStoriesData: "RealmsStoriesData";
|
|
113
113
|
readonly LevelDat: "LevelDat";
|
|
114
|
+
readonly WorldClocks: "WorldClocks";
|
|
114
115
|
readonly ForcedWorldCorruption: "ForcedWorldCorruption";
|
|
115
116
|
readonly Unknown: "Unknown";
|
|
116
117
|
};
|
|
@@ -1145,6 +1146,44 @@ export declare const entryContentTypeToFormatMap: {
|
|
|
1145
1146
|
*/
|
|
1146
1147
|
readonly rawFileExtension: "dat";
|
|
1147
1148
|
};
|
|
1149
|
+
/**
|
|
1150
|
+
* The content type of the `WorldClocks` LevelDB key, which serves an unknown purpose.
|
|
1151
|
+
*
|
|
1152
|
+
* @see {@link NBTSchemas.nbtSchemas.WorldClocks}
|
|
1153
|
+
*
|
|
1154
|
+
* @since 1.26.10 (maybe 1.26.0)
|
|
1155
|
+
*
|
|
1156
|
+
* @todo Update the linked NBT schema once it is known the structure of the items of the `clocks` list.
|
|
1157
|
+
* @todo Figure out that this is used for.
|
|
1158
|
+
* @todo Figure out what preview and full release this was actually added in.
|
|
1159
|
+
*/
|
|
1160
|
+
readonly WorldClocks: {
|
|
1161
|
+
/**
|
|
1162
|
+
* The format type of the data.
|
|
1163
|
+
*/
|
|
1164
|
+
readonly type: "NBT";
|
|
1165
|
+
/**
|
|
1166
|
+
* The default value to use when initializing a new entry.
|
|
1167
|
+
*
|
|
1168
|
+
* Value:
|
|
1169
|
+
* ```json
|
|
1170
|
+
* {
|
|
1171
|
+
* type: "compound",
|
|
1172
|
+
* name: "",
|
|
1173
|
+
* value: {
|
|
1174
|
+
* clocks: {
|
|
1175
|
+
* type: "list",
|
|
1176
|
+
* value: {
|
|
1177
|
+
* type: "end",
|
|
1178
|
+
* value: [],
|
|
1179
|
+
* },
|
|
1180
|
+
* },
|
|
1181
|
+
* },
|
|
1182
|
+
* }
|
|
1183
|
+
* ```
|
|
1184
|
+
*/
|
|
1185
|
+
readonly defaultValue: Buffer<ArrayBufferLike>;
|
|
1186
|
+
};
|
|
1148
1187
|
/**
|
|
1149
1188
|
* Bounding boxes for structures, including structure spawns (such as a Pillager Outpost)
|
|
1150
1189
|
* and volumes where mobs cannot spawn through the normal biome-based means (such as
|
package/LevelUtils.js
CHANGED
|
@@ -428,6 +428,7 @@ export const DBEntryContentTypes = [
|
|
|
428
428
|
"LevelChunkMetaDataDictionary",
|
|
429
429
|
"RealmsStoriesData",
|
|
430
430
|
"LevelDat",
|
|
431
|
+
"WorldClocks",
|
|
431
432
|
// Dev Version
|
|
432
433
|
"ForcedWorldCorruption",
|
|
433
434
|
// Misc.
|
|
@@ -503,6 +504,7 @@ export const DBEntryContentTypesGrouping = {
|
|
|
503
504
|
LevelChunkMetaDataDictionary: "LevelChunkMetaDataDictionary",
|
|
504
505
|
RealmsStoriesData: "RealmsStoriesData",
|
|
505
506
|
LevelDat: "LevelDat",
|
|
507
|
+
WorldClocks: "WorldClocks",
|
|
506
508
|
// Dev Version
|
|
507
509
|
ForcedWorldCorruption: "ForcedWorldCorruption",
|
|
508
510
|
// Misc.
|
|
@@ -2085,6 +2087,56 @@ export const entryContentTypeToFormatMap = {
|
|
|
2085
2087
|
*/
|
|
2086
2088
|
rawFileExtension: "dat",
|
|
2087
2089
|
},
|
|
2090
|
+
/**
|
|
2091
|
+
* The content type of the `WorldClocks` LevelDB key, which serves an unknown purpose.
|
|
2092
|
+
*
|
|
2093
|
+
* @see {@link NBTSchemas.nbtSchemas.WorldClocks}
|
|
2094
|
+
*
|
|
2095
|
+
* @since 1.26.10 (maybe 1.26.0)
|
|
2096
|
+
*
|
|
2097
|
+
* @todo Update the linked NBT schema once it is known the structure of the items of the `clocks` list.
|
|
2098
|
+
* @todo Figure out that this is used for.
|
|
2099
|
+
* @todo Figure out what preview and full release this was actually added in.
|
|
2100
|
+
*/
|
|
2101
|
+
WorldClocks: {
|
|
2102
|
+
/**
|
|
2103
|
+
* The format type of the data.
|
|
2104
|
+
*/
|
|
2105
|
+
type: "NBT",
|
|
2106
|
+
/**
|
|
2107
|
+
* The default value to use when initializing a new entry.
|
|
2108
|
+
*
|
|
2109
|
+
* Value:
|
|
2110
|
+
* ```json
|
|
2111
|
+
* {
|
|
2112
|
+
* type: "compound",
|
|
2113
|
+
* name: "",
|
|
2114
|
+
* value: {
|
|
2115
|
+
* clocks: {
|
|
2116
|
+
* type: "list",
|
|
2117
|
+
* value: {
|
|
2118
|
+
* type: "end",
|
|
2119
|
+
* value: [],
|
|
2120
|
+
* },
|
|
2121
|
+
* },
|
|
2122
|
+
* },
|
|
2123
|
+
* }
|
|
2124
|
+
* ```
|
|
2125
|
+
*/
|
|
2126
|
+
defaultValue: NBT.writeUncompressed({
|
|
2127
|
+
type: "compound",
|
|
2128
|
+
name: "",
|
|
2129
|
+
value: {
|
|
2130
|
+
clocks: {
|
|
2131
|
+
type: "list",
|
|
2132
|
+
value: {
|
|
2133
|
+
type: "end",
|
|
2134
|
+
value: [],
|
|
2135
|
+
},
|
|
2136
|
+
},
|
|
2137
|
+
},
|
|
2138
|
+
}, "little"),
|
|
2139
|
+
},
|
|
2088
2140
|
/**
|
|
2089
2141
|
* Bounding boxes for structures, including structure spawns (such as a Pillager Outpost)
|
|
2090
2142
|
* and volumes where mobs cannot spawn through the normal biome-based means (such as
|
|
@@ -2604,6 +2656,7 @@ export function getKeyDisplayName(key) {
|
|
|
2604
2656
|
case "VillagePlayers":
|
|
2605
2657
|
case "VillageRaid":
|
|
2606
2658
|
case "Villages":
|
|
2659
|
+
case "WorldClocks":
|
|
2607
2660
|
case "Unknown":
|
|
2608
2661
|
default:
|
|
2609
2662
|
return key.toString("binary");
|
|
@@ -2702,6 +2755,8 @@ export function getContentTypeFromDBKey(key) {
|
|
|
2702
2755
|
return "DynamicProperties";
|
|
2703
2756
|
case "LevelChunkMetaDataDictionary":
|
|
2704
2757
|
return "LevelChunkMetaDataDictionary";
|
|
2758
|
+
case "WorldClocks":
|
|
2759
|
+
return "WorldClocks";
|
|
2705
2760
|
case "SST_SALOG":
|
|
2706
2761
|
case "SST_WORD":
|
|
2707
2762
|
case "SST_WORD_":
|