@kunosyn/shatterbox 0.0.1
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/LICENSE +21 -0
- package/README.md +35 -0
- package/package.json +36 -0
- package/src/Effects.d.ts +134 -0
- package/src/Effects.luau +114 -0
- package/src/Settings.luau +75 -0
- package/src/index.d.ts +617 -0
- package/src/init.luau +2580 -0
- package/src/lib/Client.luau +4020 -0
- package/src/lib/InitializeShatterboxClients.client.luau +10 -0
- package/src/lib/ObjectCache.luau +198 -0
- package/src/lib/PartOperations.luau +673 -0
- package/src/lib/Server.luau +4425 -0
- package/src/lib/VertexMath.luau +403 -0
- package/src/types.ts +504 -0
- package/src/util/HitboxVisualizer.luau +101 -0
- package/src/util/TaggedArray.luau +66 -0
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,617 @@
|
|
|
1
|
+
/// <reference types="@rbxts/types" />
|
|
2
|
+
|
|
3
|
+
import Effects from "./Effects";
|
|
4
|
+
import type {
|
|
5
|
+
HitboxObject,
|
|
6
|
+
DestructionParams,
|
|
7
|
+
Settings,
|
|
8
|
+
WorldInfo,
|
|
9
|
+
OnDestructCompleted,
|
|
10
|
+
ImaginaryDestructionParams,
|
|
11
|
+
ImaginaryVoxel,
|
|
12
|
+
DestroyedVoxelInfo,
|
|
13
|
+
OnVoxelDestruct,
|
|
14
|
+
VertexMath
|
|
15
|
+
} from "./types";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Shatterbox - A voxel destruction system for Roblox
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const shatterbox = new Shatterbox();
|
|
23
|
+
* shatterbox.Start();
|
|
24
|
+
*
|
|
25
|
+
* // Destroy parts around a ball
|
|
26
|
+
* shatterbox.Destroy({
|
|
27
|
+
* CFrame: new CFrame(0, 10, 0),
|
|
28
|
+
* Size: new Vector3(5, 5, 5),
|
|
29
|
+
* Shape: Enum.PartType.Ball
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
declare class Shatterbox {
|
|
34
|
+
/**
|
|
35
|
+
* Settings configuration for this Shatterbox instance
|
|
36
|
+
* @readonly
|
|
37
|
+
*/
|
|
38
|
+
public readonly Settings: Settings;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Vertex math utilities for intersection testing
|
|
42
|
+
* @readonly
|
|
43
|
+
*/
|
|
44
|
+
public readonly VertexMath: VertexMath;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Default Effects for Voxel Destruction.
|
|
48
|
+
* @readonly
|
|
49
|
+
*/
|
|
50
|
+
public readonly DefaultEffects: Effects;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Whether the Shatterbox instance has been started
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
private started: boolean;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Creates a new Shatterbox instance with optional custom settings
|
|
60
|
+
*
|
|
61
|
+
* @param settings Optional configuration settings. If not provided, uses default settings.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* // With default settings
|
|
66
|
+
* const shatterbox = new Shatterbox();
|
|
67
|
+
*
|
|
68
|
+
* // With custom settings
|
|
69
|
+
* const shatterbox = new Shatterbox({
|
|
70
|
+
* DefaultGridSize: 2,
|
|
71
|
+
* UseGreedyMeshing: true,
|
|
72
|
+
* MaxDivisionsPerFrame: 100
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
constructor(settings?: Partial<Settings>);
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Starts the Shatterbox system. Must be called before using any destruction methods.
|
|
80
|
+
* Can only be called once per instance.
|
|
81
|
+
*
|
|
82
|
+
* Initializes network events, effect registries, and starts the heartbeat worker.
|
|
83
|
+
*
|
|
84
|
+
* @throws Will warn if called more than once on the same instance
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* const shatterbox = new Shatterbox();
|
|
89
|
+
* shatterbox.Start();
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
public Start(): void;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Registers an effect callback for voxel destruction
|
|
96
|
+
*
|
|
97
|
+
* Effect callbacks are executed when voxels are destroyed, allowing you to:
|
|
98
|
+
* - Apply physics effects
|
|
99
|
+
* - Create particle effects
|
|
100
|
+
* - Play sounds
|
|
101
|
+
* - Add custom behavior to destroyed voxels
|
|
102
|
+
*
|
|
103
|
+
* @param name Unique name for the effect (case-insensitive)
|
|
104
|
+
* @param callback Function to execute when a voxel is destroyed
|
|
105
|
+
*
|
|
106
|
+
* @throws Asserts if name is not a string
|
|
107
|
+
* @throws Asserts if an effect with this name already exists
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```ts
|
|
111
|
+
* shatterbox.RegisterOnVoxelDestruct("explosion", (voxel, info) => {
|
|
112
|
+
* voxel.Anchored = false;
|
|
113
|
+
* voxel.Velocity = info.CuttingPart.CFrame.LookVector.mul(50);
|
|
114
|
+
*
|
|
115
|
+
* const explosion = new Instance("Explosion");
|
|
116
|
+
* explosion.Position = voxel.Position;
|
|
117
|
+
* explosion.Parent = game.Workspace;
|
|
118
|
+
* });
|
|
119
|
+
*
|
|
120
|
+
* // Use the effect in destruction
|
|
121
|
+
* shatterbox.Destroy(part, undefined, undefined, "explosion");
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
public RegisterOnVoxelDestruct(name: string, callback: OnVoxelDestruct): void;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Performs voxel destruction around the intersecting part.
|
|
128
|
+
* Operations are queued and processed over multiple frames to maintain performance.
|
|
129
|
+
*
|
|
130
|
+
* Supports multiple syntaxes:
|
|
131
|
+
* 1. Part/Model as cutting shape
|
|
132
|
+
* 2. WorldInfo table (CFrame, Size, Shape)
|
|
133
|
+
* 3. DestructionParams object with all options
|
|
134
|
+
*
|
|
135
|
+
* @param intersectingPart The cutting shape or params object
|
|
136
|
+
* @param FilterTagged Optional tag(s) to filter which parts can be destroyed
|
|
137
|
+
* @param CleanupDelay Time in seconds before destroyed parts are restored (0 = never restore)
|
|
138
|
+
* @param OnVoxelDestruct Name of the registered effect callback to execute
|
|
139
|
+
* @param GridSize Size of each voxel in studs (smaller = more detailed destruction)
|
|
140
|
+
* @param SkipEncapsulatedVoxels If true, don't create voxels fully inside the cutting part
|
|
141
|
+
* @param OnDestructCompleted Callback when destruction completes
|
|
142
|
+
* @param UserData Custom data passed to the effect callback
|
|
143
|
+
* @param ExcludePlayersReplication Players to exclude from replication (server-side only)
|
|
144
|
+
* @param SkipFloors If true, don't destroy floor surfaces
|
|
145
|
+
* @param SkipWalls If true, don't destroy wall surfaces
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* // Simple destruction with a part
|
|
150
|
+
* shatterbox.Destroy(explosionPart);
|
|
151
|
+
*
|
|
152
|
+
* // Destruction with WorldInfo
|
|
153
|
+
* shatterbox.Destroy({
|
|
154
|
+
* CFrame: new CFrame(0, 10, 0),
|
|
155
|
+
* Size: new Vector3(10, 10, 10),
|
|
156
|
+
* Shape: Enum.PartType.Ball
|
|
157
|
+
* });
|
|
158
|
+
*
|
|
159
|
+
* // Full params with effect and cleanup
|
|
160
|
+
* shatterbox.Destroy(
|
|
161
|
+
* explosionPart,
|
|
162
|
+
* "Destructible", // Only destroy parts tagged "Destructible"
|
|
163
|
+
* 5, // Restore after 5 seconds
|
|
164
|
+
* "explosion", // Use "explosion" effect
|
|
165
|
+
* 2, // 2-stud voxels
|
|
166
|
+
* false,
|
|
167
|
+
* (count, groups) => print(`Destroyed ${count} voxels`)
|
|
168
|
+
* );
|
|
169
|
+
*
|
|
170
|
+
* // Using params object
|
|
171
|
+
* shatterbox.Destroy({
|
|
172
|
+
* CuttingPart: {
|
|
173
|
+
* CFrame: missile.CFrame,
|
|
174
|
+
* Size: new Vector3(5, 5, 5),
|
|
175
|
+
* Shape: Enum.PartType.Ball
|
|
176
|
+
* },
|
|
177
|
+
* OnVoxelDestruct: "explosion",
|
|
178
|
+
* GridSize: 1.5,
|
|
179
|
+
* CleanupDelay: 10,
|
|
180
|
+
* SkipFloors: true
|
|
181
|
+
* });
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
public Destroy(
|
|
185
|
+
intersectingPart: Part | Model | WorldInfo | DestructionParams,
|
|
186
|
+
FilterTagged?: string | Array<string>,
|
|
187
|
+
CleanupDelay?: number,
|
|
188
|
+
OnVoxelDestruct?: string,
|
|
189
|
+
GridSize?: number,
|
|
190
|
+
SkipEncapsulatedVoxels?: boolean,
|
|
191
|
+
OnDestructCompleted?: OnDestructCompleted,
|
|
192
|
+
UserData?: Record<string, unknown>,
|
|
193
|
+
ExcludePlayersReplication?: Array<Player>,
|
|
194
|
+
SkipFloors?: boolean,
|
|
195
|
+
SkipWalls?: boolean
|
|
196
|
+
): void;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Performs instant voxel destruction, yielding until the next Heartbeat.
|
|
200
|
+
* Returns imaginary voxels (data structures) that can be instantiated as real parts.
|
|
201
|
+
*
|
|
202
|
+
* Use this when you want full control over how voxels are created, or when you need
|
|
203
|
+
* to inspect/modify voxels before instantiating them.
|
|
204
|
+
*
|
|
205
|
+
* @returns A tuple of [imaginaryVoxels, existingDebris]
|
|
206
|
+
* - imaginaryVoxels: Array of voxel data that can be instantiated with InstantiateImaginaryVoxel
|
|
207
|
+
* - existingDebris: Array of existing debris parts that were in the destruction area
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```ts
|
|
211
|
+
* // Get imaginary voxels without creating them
|
|
212
|
+
* const [voxels, debris] = shatterbox.ImaginaryVoxels({
|
|
213
|
+
* CFrame: new CFrame(0, 10, 0),
|
|
214
|
+
* Size: new Vector3(5, 5, 5),
|
|
215
|
+
* Shape: Enum.PartType.Ball
|
|
216
|
+
* });
|
|
217
|
+
*
|
|
218
|
+
* print(`Would create ${voxels.size()} voxels`);
|
|
219
|
+
*
|
|
220
|
+
* // Create only edge voxels with custom properties
|
|
221
|
+
* for (const voxel of voxels) {
|
|
222
|
+
* if (voxel.isEdge) {
|
|
223
|
+
* const part = shatterbox.InstantiateImaginaryVoxel(voxel);
|
|
224
|
+
* part.BrickColor = BrickColor.Red();
|
|
225
|
+
* part.Anchored = false;
|
|
226
|
+
* }
|
|
227
|
+
* }
|
|
228
|
+
*
|
|
229
|
+
* // Handle existing debris
|
|
230
|
+
* for (const debris of debris) {
|
|
231
|
+
* debris.BrickColor = BrickColor.Yellow();
|
|
232
|
+
* }
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
public ImaginaryVoxels(
|
|
236
|
+
intersectingPart: Part | Model | WorldInfo | ImaginaryDestructionParams,
|
|
237
|
+
FilterTagged?: string | Array<string>,
|
|
238
|
+
CleanupDelay?: number,
|
|
239
|
+
GridSize?: number,
|
|
240
|
+
SkipEncapsulatedVoxels?: boolean,
|
|
241
|
+
ExcludePlayersReplication?: Array<Player>,
|
|
242
|
+
SkipFloors?: boolean,
|
|
243
|
+
SkipWalls?: boolean
|
|
244
|
+
): LuaTuple<[Array<ImaginaryVoxel>, Array<BasePart>]>;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Instantiates an imaginary voxel as a real Part in the workspace.
|
|
248
|
+
*
|
|
249
|
+
* The created part will:
|
|
250
|
+
* - Be automatically parented to the appropriate location
|
|
251
|
+
* - Have the DebrisTag tag (unless doNotGiveDebrisTag is true)
|
|
252
|
+
* - Be registered in the dirty group system
|
|
253
|
+
*
|
|
254
|
+
* @param imaginaryVoxel The imaginary voxel data from ImaginaryVoxels()
|
|
255
|
+
* @param doNotGiveDebrisTag If true, don't add the DebrisTag to the created part
|
|
256
|
+
* @returns The created Part instance
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```ts
|
|
260
|
+
* const [voxels] = shatterbox.ImaginaryVoxels(explosionPart);
|
|
261
|
+
*
|
|
262
|
+
* // Create all voxels as debris
|
|
263
|
+
* for (const voxel of voxels) {
|
|
264
|
+
* const part = shatterbox.InstantiateImaginaryVoxel(voxel);
|
|
265
|
+
* part.Anchored = false;
|
|
266
|
+
* }
|
|
267
|
+
*
|
|
268
|
+
* // Create voxels without debris tag (for custom tracking)
|
|
269
|
+
* for (const voxel of voxels) {
|
|
270
|
+
* const part = shatterbox.InstantiateImaginaryVoxel(voxel, true);
|
|
271
|
+
* // Add your own custom tag or tracking
|
|
272
|
+
* part.SetAttribute("CustomVoxel", true);
|
|
273
|
+
* }
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
public InstantiateImaginaryVoxel(
|
|
277
|
+
imaginaryVoxel: ImaginaryVoxel,
|
|
278
|
+
doNotGiveDebrisTag?: boolean
|
|
279
|
+
): Part;
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Makes a voxel fall realistically with physics and replicates it to clients.
|
|
283
|
+
*
|
|
284
|
+
* **Server-side only.**
|
|
285
|
+
*
|
|
286
|
+
* Puppets are physics-enabled parts that are efficiently replicated to clients
|
|
287
|
+
* using compressed state updates. The system automatically:
|
|
288
|
+
* - Manages network ownership
|
|
289
|
+
* - Compresses position/rotation data
|
|
290
|
+
* - Handles client-side interpolation
|
|
291
|
+
* - Auto-anchors when sleeping
|
|
292
|
+
* - Cleans up old puppets when limit is reached
|
|
293
|
+
*
|
|
294
|
+
* @param voxel The part to turn into a falling puppet
|
|
295
|
+
*
|
|
296
|
+
* @throws Asserts if called on client
|
|
297
|
+
* @throws Warns if network ownership cannot be set
|
|
298
|
+
*
|
|
299
|
+
* @example
|
|
300
|
+
* ```ts
|
|
301
|
+
* // Create falling debris
|
|
302
|
+
* const [voxels] = shatterbox.ImaginaryVoxels(explosionPart);
|
|
303
|
+
*
|
|
304
|
+
* for (const voxel of voxels) {
|
|
305
|
+
* const part = shatterbox.InstantiateImaginaryVoxel(voxel);
|
|
306
|
+
*
|
|
307
|
+
* // Apply force
|
|
308
|
+
* const direction = voxel.CFrame.Position.sub(explosionPart.Position).Unit;
|
|
309
|
+
* part.AssemblyLinearVelocity = direction.mul(50);
|
|
310
|
+
*
|
|
311
|
+
* // Make it fall with replication
|
|
312
|
+
* shatterbox.Puppeteer(part);
|
|
313
|
+
* }
|
|
314
|
+
* ```
|
|
315
|
+
*/
|
|
316
|
+
public Puppeteer(voxel: Part): void;
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Creates fake puppets on the client for testing purposes.
|
|
320
|
+
*
|
|
321
|
+
* **Client-side only.**
|
|
322
|
+
*
|
|
323
|
+
* Useful for testing destruction effects without server replication.
|
|
324
|
+
*
|
|
325
|
+
* @param fakePuppets Array of parts to treat as puppets
|
|
326
|
+
*
|
|
327
|
+
* @example
|
|
328
|
+
* ```ts
|
|
329
|
+
* // Client-side testing
|
|
330
|
+
* const testParts: Part[] = [];
|
|
331
|
+
* for (let i = 0; i < 10; i++) {
|
|
332
|
+
* const part = new Instance("Part");
|
|
333
|
+
* part.Size = new Vector3(2, 2, 2);
|
|
334
|
+
* part.Position = new Vector3(i * 3, 10, 0);
|
|
335
|
+
* part.Parent = game.Workspace;
|
|
336
|
+
* testParts.push(part);
|
|
337
|
+
* }
|
|
338
|
+
*
|
|
339
|
+
* shatterbox.FakeClientPuppets(testParts);
|
|
340
|
+
* ```
|
|
341
|
+
*/
|
|
342
|
+
public FakeClientPuppets(fakePuppets: Array<Part>): void;
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Creates a hitbox object with additional functionality for destruction.
|
|
346
|
+
*
|
|
347
|
+
* Hitboxes provide:
|
|
348
|
+
* - Welding to moving parts
|
|
349
|
+
* - Continuous destruction (raycast-like)
|
|
350
|
+
* - Velocity prediction for fast-moving objects
|
|
351
|
+
* - Start/Stop control
|
|
352
|
+
*
|
|
353
|
+
* @returns A hitbox object with methods for destruction and movement
|
|
354
|
+
*
|
|
355
|
+
* @example
|
|
356
|
+
* ```ts
|
|
357
|
+
* // Create a projectile hitbox
|
|
358
|
+
* const hitbox = shatterbox.CreateHitbox();
|
|
359
|
+
* hitbox.Size = new Vector3(2, 2, 2);
|
|
360
|
+
* hitbox.Shape = Enum.PartType.Ball;
|
|
361
|
+
* hitbox.OnVoxelDestruct = "explosion";
|
|
362
|
+
* hitbox.GridSize = 1;
|
|
363
|
+
*
|
|
364
|
+
* // Weld to projectile
|
|
365
|
+
* hitbox.WeldTo(projectile);
|
|
366
|
+
* hitbox.VelocityPrediction = true; // Enable for fast projectiles
|
|
367
|
+
* hitbox.Start();
|
|
368
|
+
*
|
|
369
|
+
* // Cleanup when done
|
|
370
|
+
* projectile.Touched.Connect(() => {
|
|
371
|
+
* hitbox.Stop();
|
|
372
|
+
* hitbox.DestroyHitbox();
|
|
373
|
+
* });
|
|
374
|
+
*
|
|
375
|
+
* // Manual control hitbox
|
|
376
|
+
* const controlledHitbox = shatterbox.CreateHitbox();
|
|
377
|
+
* controlledHitbox.DestructDelay = 0.1; // Destroy every 0.1 seconds
|
|
378
|
+
*
|
|
379
|
+
* game.GetService("RunService").Heartbeat.Connect(() => {
|
|
380
|
+
* controlledHitbox.CFrame = tool.Handle.CFrame;
|
|
381
|
+
* });
|
|
382
|
+
*
|
|
383
|
+
* controlledHitbox.Start();
|
|
384
|
+
* ```
|
|
385
|
+
*/
|
|
386
|
+
public CreateHitbox(): HitboxObject;
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Resets an area without reverting ownership of parts.
|
|
390
|
+
*
|
|
391
|
+
* Undoes all destruction within the specified area while maintaining the
|
|
392
|
+
* current dirty group structure. Useful for resetting specific zones without
|
|
393
|
+
* affecting the rest of the map.
|
|
394
|
+
*
|
|
395
|
+
* @param area The area to reset (Part or WorldInfo with CFrame and Size)
|
|
396
|
+
*
|
|
397
|
+
* @example
|
|
398
|
+
* ```ts
|
|
399
|
+
* // Reset using a part
|
|
400
|
+
* const resetZone = game.Workspace.WaitForChild("ResetZone") as Part;
|
|
401
|
+
* shatterbox.ResetArea(resetZone);
|
|
402
|
+
*
|
|
403
|
+
* // Reset using WorldInfo
|
|
404
|
+
* shatterbox.ResetArea({
|
|
405
|
+
* CFrame: new CFrame(0, 0, 0),
|
|
406
|
+
* Size: new Vector3(50, 50, 50)
|
|
407
|
+
* });
|
|
408
|
+
*
|
|
409
|
+
* // Reset around player
|
|
410
|
+
* game.GetService("Players").PlayerAdded.Connect((player) => {
|
|
411
|
+
* const character = player.Character || player.CharacterAdded.Wait()[0];
|
|
412
|
+
* const hrp = character.WaitForChild("HumanoidRootPart") as Part;
|
|
413
|
+
*
|
|
414
|
+
* shatterbox.ResetArea({
|
|
415
|
+
* CFrame: hrp.CFrame,
|
|
416
|
+
* Size: new Vector3(20, 20, 20)
|
|
417
|
+
* });
|
|
418
|
+
* });
|
|
419
|
+
* ```
|
|
420
|
+
*/
|
|
421
|
+
public ResetArea(area: Part | WorldInfo): void;
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Resets all modified parts to their original state.
|
|
425
|
+
*
|
|
426
|
+
* This will:
|
|
427
|
+
* - Cancel all queued operations
|
|
428
|
+
* - Terminate all greedy meshing workers
|
|
429
|
+
* - Clear smooth cleanup timers
|
|
430
|
+
* - Destroy or restore all puppets
|
|
431
|
+
* - Restore all original parts
|
|
432
|
+
*
|
|
433
|
+
* @param doNotRevertOwnership If true, keeps parts in their current ownership state
|
|
434
|
+
*
|
|
435
|
+
* @example
|
|
436
|
+
* ```ts
|
|
437
|
+
* // Complete reset
|
|
438
|
+
* shatterbox.Reset();
|
|
439
|
+
*
|
|
440
|
+
* // Reset but maintain dirty groups (for client-server sync)
|
|
441
|
+
* shatterbox.Reset(true);
|
|
442
|
+
*
|
|
443
|
+
* // Reset on round end
|
|
444
|
+
* function resetMap() {
|
|
445
|
+
* shatterbox.Reset();
|
|
446
|
+
* print("Map has been reset!");
|
|
447
|
+
* }
|
|
448
|
+
* ```
|
|
449
|
+
*/
|
|
450
|
+
public Reset(doNotRevertOwnership?: boolean): void;
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Cancels all ongoing destruction operations in the queue.
|
|
454
|
+
*
|
|
455
|
+
* This stops processing queued destructions but does not undo
|
|
456
|
+
* destructions that have already been processed.
|
|
457
|
+
*
|
|
458
|
+
* @example
|
|
459
|
+
* ```ts
|
|
460
|
+
* // Cancel all pending destructions
|
|
461
|
+
* shatterbox.ClearQueue();
|
|
462
|
+
*
|
|
463
|
+
* // Useful for stopping destruction on game state change
|
|
464
|
+
* function onRoundEnd() {
|
|
465
|
+
* shatterbox.ClearQueue(); // Stop processing destructions
|
|
466
|
+
* wait(1);
|
|
467
|
+
* shatterbox.Reset(); // Then reset the map
|
|
468
|
+
* }
|
|
469
|
+
* ```
|
|
470
|
+
*/
|
|
471
|
+
public ClearQueue(): void;
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Returns the original part associated with a DirtyGroupID.
|
|
475
|
+
*
|
|
476
|
+
* The original part is never destroyed by Shatterbox, just has its parent
|
|
477
|
+
* set to nil. This allows the system to restore parts efficiently.
|
|
478
|
+
*
|
|
479
|
+
* @param dirtyGroupID The ID of the dirty group
|
|
480
|
+
* @returns The original part, or undefined if not found
|
|
481
|
+
*
|
|
482
|
+
* @example
|
|
483
|
+
* ```ts
|
|
484
|
+
* // Get original part from a voxel
|
|
485
|
+
* const voxel = game.Workspace.FindFirstChild("Voxel") as Part;
|
|
486
|
+
* const dirtyGroupID = voxel.GetAttribute("DirtyGroupID") as string;
|
|
487
|
+
*
|
|
488
|
+
* if (dirtyGroupID) {
|
|
489
|
+
* const original = shatterbox.GetOriginalPart(dirtyGroupID);
|
|
490
|
+
* if (original) {
|
|
491
|
+
* print(`Original part: ${original.Name}`);
|
|
492
|
+
* print(`Original size: ${original.Size}`);
|
|
493
|
+
* }
|
|
494
|
+
* }
|
|
495
|
+
* ```
|
|
496
|
+
*/
|
|
497
|
+
public GetOriginalPart(dirtyGroupID: string): Part | undefined;
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Converts a point to voxel space distance relative to the voxel.
|
|
501
|
+
*
|
|
502
|
+
* Returns a vector indicating how many voxels away the point is on each
|
|
503
|
+
* local axis as fractional quantities. Useful for spatial queries and
|
|
504
|
+
* calculating voxel-based distances.
|
|
505
|
+
*
|
|
506
|
+
* @param voxel The reference voxel part
|
|
507
|
+
* @param point The world space point to convert
|
|
508
|
+
* @returns Distance vector in voxel space
|
|
509
|
+
*
|
|
510
|
+
* @example
|
|
511
|
+
* ```ts
|
|
512
|
+
* const voxel = game.Workspace.WaitForChild("Voxel") as Part;
|
|
513
|
+
* const targetPos = new Vector3(10, 10, 10);
|
|
514
|
+
*
|
|
515
|
+
* const distance = shatterbox.VoxelDistanceVector(voxel, targetPos);
|
|
516
|
+
* print(`Distance: ${distance.X}x, ${distance.Y}y, ${distance.Z}z voxels`);
|
|
517
|
+
*
|
|
518
|
+
* // Check if point is within 5 voxels
|
|
519
|
+
* if (distance.Magnitude < 5) {
|
|
520
|
+
* print("Point is close to voxel");
|
|
521
|
+
* }
|
|
522
|
+
* ```
|
|
523
|
+
*/
|
|
524
|
+
public VoxelDistanceVector(voxel: Part, point: Vector3): Vector3;
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Returns how many voxels a box has on each axis as fractional quantities.
|
|
528
|
+
*
|
|
529
|
+
* Minimum of 1 on each axis (a box is always at least 1 voxel large).
|
|
530
|
+
*
|
|
531
|
+
* @param voxel The reference voxel part (for voxel size)
|
|
532
|
+
* @param boxSize The size of the box to measure
|
|
533
|
+
* @returns Voxel count vector
|
|
534
|
+
*
|
|
535
|
+
* @example
|
|
536
|
+
* ```ts
|
|
537
|
+
* const voxel = game.Workspace.WaitForChild("Voxel") as Part;
|
|
538
|
+
* const testSize = new Vector3(10, 5, 8);
|
|
539
|
+
*
|
|
540
|
+
* const voxelCount = shatterbox.VoxelCountVector(voxel, testSize);
|
|
541
|
+
* print(`Would create ${voxelCount.X * voxelCount.Y * voxelCount.Z} voxels`);
|
|
542
|
+
*
|
|
543
|
+
* // Estimate performance impact
|
|
544
|
+
* const totalVoxels = voxelCount.X * voxelCount.Y * voxelCount.Z;
|
|
545
|
+
* if (totalVoxels > 1000) {
|
|
546
|
+
* warn("Large destruction - may impact performance");
|
|
547
|
+
* }
|
|
548
|
+
* ```
|
|
549
|
+
*/
|
|
550
|
+
public VoxelCountVector(voxel: Part, boxSize: Vector3): Vector3;
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Returns true if the contains part is fully encapsulated by the part.
|
|
554
|
+
*
|
|
555
|
+
* @param part The container part
|
|
556
|
+
* @param contains The part to check if it's contained (must be a Block part)
|
|
557
|
+
* @returns True if fully contained, false otherwise
|
|
558
|
+
*
|
|
559
|
+
* @throws Asserts if part is not a Part
|
|
560
|
+
* @throws Asserts if contains is not a Block Part
|
|
561
|
+
*
|
|
562
|
+
* @example
|
|
563
|
+
* ```ts
|
|
564
|
+
* const container = game.Workspace.WaitForChild("Container") as Part;
|
|
565
|
+
* const testPart = game.Workspace.WaitForChild("TestPart") as Part;
|
|
566
|
+
*
|
|
567
|
+
* if (shatterbox.PartEncapsulatesBlockPart(container, testPart)) {
|
|
568
|
+
* print("TestPart is fully inside Container");
|
|
569
|
+
* } else {
|
|
570
|
+
* print("TestPart is partially or not inside Container");
|
|
571
|
+
* }
|
|
572
|
+
* ```
|
|
573
|
+
*/
|
|
574
|
+
public PartEncapsulatesBlockPart(part: Part, contains: Part): boolean;
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Prints the current state of Shatterbox for debugging.
|
|
578
|
+
*
|
|
579
|
+
* Shows:
|
|
580
|
+
* - ShatterQueue length
|
|
581
|
+
* - Active greedy meshing workers
|
|
582
|
+
* - Dirty group counts
|
|
583
|
+
* - Operation processing counts
|
|
584
|
+
*
|
|
585
|
+
* Output is formatted for easy reading in the console.
|
|
586
|
+
*
|
|
587
|
+
* @example
|
|
588
|
+
* ```ts
|
|
589
|
+
* // Debug performance issues
|
|
590
|
+
* shatterbox.PrintState();
|
|
591
|
+
*
|
|
592
|
+
* // Monitor queue size
|
|
593
|
+
* game.GetService("RunService").Heartbeat.Connect(() => {
|
|
594
|
+
* if (frameCount % 60 === 0) {
|
|
595
|
+
* shatterbox.PrintState();
|
|
596
|
+
* }
|
|
597
|
+
* });
|
|
598
|
+
* ```
|
|
599
|
+
*/
|
|
600
|
+
public PrintState(): void;
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Gets a setting value, falling back to default if not set in instance settings.
|
|
604
|
+
*
|
|
605
|
+
* @param settingName Name of the setting to retrieve
|
|
606
|
+
* @returns The setting value
|
|
607
|
+
*
|
|
608
|
+
* @example
|
|
609
|
+
* ```ts
|
|
610
|
+
* const gridSize = shatterbox.UseSetting<number>("DefaultGridSize");
|
|
611
|
+
* const useGreedy = shatterbox.UseSetting<boolean>("UseGreedyMeshing");
|
|
612
|
+
* ```
|
|
613
|
+
*/
|
|
614
|
+
public UseSetting<T>(settingName: keyof Settings): T;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
export = Shatterbox;
|