@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.
@@ -0,0 +1,10 @@
1
+ --#selene: allow(unused_variable)
2
+ --#selene: allow(multiple_statements)
3
+
4
+ local RunService = game:GetService("RunService")
5
+
6
+ local ReplicatedStorage = game:GetService("ReplicatedStorage")
7
+
8
+ repeat RunService.Heartbeat:Wait() until ReplicatedStorage:FindFirstChild("BLINK_RELIABLE_REMOTE")
9
+
10
+ local Shatterbox = require(script.Parent.Parent:WaitForChild("Main"))
@@ -0,0 +1,198 @@
1
+ local RunService = game:GetService("RunService")
2
+ --!strict
3
+ --!native
4
+ local FAR_AWAY_CFRAME = CFrame.new(2^24, 2^24, 2^24)
5
+ local EXPAND_BY_AMOUNT = 50
6
+
7
+ local MovingParts = table.create(10_000)
8
+ local MovingCFrames = table.create(10_000)
9
+
10
+ local ScheduledUpdate = false
11
+ local function UpdateMovement()
12
+ while true do
13
+ workspace:BulkMoveTo(MovingParts, MovingCFrames, Enum.BulkMoveMode.FireCFrameChanged)
14
+
15
+ table.clear(MovingParts)
16
+ table.clear(MovingCFrames)
17
+
18
+ ScheduledUpdate = false
19
+ coroutine.yield()
20
+ end
21
+ end
22
+ local UpdateMovementThread = coroutine.create(UpdateMovement)
23
+
24
+ local Cache = {}
25
+ Cache.__index = Cache
26
+
27
+ function Cache:_GetNew(Amount: number, Warn: boolean)
28
+ if Warn then
29
+ warn(`ObjectCache: Cache retrieval exceeded preallocated amount! expanding by {Amount}...`)
30
+ end
31
+
32
+ local FreeObjectsContainer = self._FreeObjects
33
+ local InitialLength = #self._FreeObjects
34
+ local CacheHolder = self.CacheHolder
35
+
36
+ local IsTemplateModel = self._IsTemplateModel
37
+ local Template: Model | BasePart = self._Template
38
+
39
+ local TargetParts = table.create(Amount)
40
+ local TargetCFrames = table.create(Amount)
41
+ local AddedObjects = table.create(Amount)
42
+ for Index = InitialLength + 1, InitialLength + Amount do
43
+ local Object = Template:Clone()
44
+ local ObjectRoot: BasePart = if IsTemplateModel then (Object:: Model).PrimaryPart:: BasePart else Object:: BasePart
45
+
46
+ FreeObjectsContainer[Index] = ObjectRoot
47
+
48
+ local OffsetIndex = Index - InitialLength
49
+ TargetParts[OffsetIndex] = ObjectRoot
50
+ TargetCFrames[OffsetIndex] = FAR_AWAY_CFRAME
51
+ AddedObjects[OffsetIndex] = Object
52
+ end
53
+
54
+ workspace:BulkMoveTo(TargetParts, TargetCFrames, Enum.BulkMoveMode.FireCFrameChanged)
55
+
56
+ for _, Object in AddedObjects do
57
+ (Object:: Instance).Parent = CacheHolder
58
+ end
59
+
60
+ return table.remove(FreeObjectsContainer)
61
+ end
62
+
63
+ function Cache:GetPart(PartCFrame: CFrame?): BasePart
64
+ local Part = table.remove(self._FreeObjects) or self:_GetNew(self._ExpandAmount, true)
65
+
66
+
67
+ for _, tag in ipairs(Part:GetTags()) do -- I added these two loops, not sure if it's the best placement
68
+ Part:RemoveTag(tag)
69
+ end
70
+ Part:AddTag("ObjectCache")
71
+
72
+ for att in pairs(Part:GetAttributes()) do
73
+ Part:SetAttribute(att)
74
+ end
75
+
76
+
77
+ self._Objects[Part] = nil
78
+ if PartCFrame then
79
+ table.insert(MovingParts, Part)
80
+ table.insert(MovingCFrames, PartCFrame)
81
+
82
+ if not ScheduledUpdate then
83
+ ScheduledUpdate = true
84
+ task.defer(UpdateMovementThread)
85
+ end
86
+ end
87
+
88
+ return Part
89
+ end
90
+ function Cache:ReturnPart(Part: BasePart)
91
+ if self._Objects[Part] then
92
+ return
93
+ end
94
+
95
+ Part:RemoveTag("ObjectCache")
96
+
97
+ Part.Parent = self.CacheHolder
98
+ Part.Anchored = true
99
+
100
+ self._Objects[Part] = true
101
+
102
+ table.insert(self._FreeObjects, Part)
103
+ table.insert(MovingParts, Part)
104
+ table.insert(MovingCFrames, FAR_AWAY_CFRAME)
105
+
106
+ if not ScheduledUpdate then
107
+ ScheduledUpdate = true
108
+ task.defer(UpdateMovementThread)
109
+ end
110
+ end
111
+
112
+ function Cache:Update()
113
+ task.spawn(UpdateMovementThread)
114
+ end
115
+
116
+ function Cache:ExpandCache(Amount: number)
117
+ assert(typeof(Amount) ~= "number" or Amount >= 0, `Invalid argument #1 to 'ObjectCache:ExpandCache' (positive number expected, got {typeof(Amount)})`)
118
+ self:_GetNew(Amount, false)
119
+ end
120
+ function Cache:SetExpandAmount(Amount: number)
121
+ assert(typeof(Amount) ~= "number" or Amount > 0, `Invalid argument #1 to 'ObjectCache:SetExpandAmount' (positive number expected, got {typeof(Amount)})`)
122
+ self._ExpandAmount = Amount
123
+ end
124
+
125
+ function Cache:IsInUse(Object: BasePart): boolean
126
+ return self._Objects[Object] == nil
127
+ end
128
+
129
+ function Cache:Destroy()
130
+ self.CacheHolder:Destroy()
131
+ end
132
+
133
+ local function GetCacheContainer()
134
+ local CacheHolder = Instance.new("Folder")
135
+ CacheHolder.Name = "ObjectCache"
136
+
137
+ return CacheHolder
138
+ end
139
+
140
+ local Constructor = {}
141
+ function Constructor.new(Template: BasePart | Model, CacheSize: number?, CachesContainer: Instance?)
142
+ local TemplateType = typeof(Template)
143
+ assert(TemplateType == "Instance", `Invalid argument #1 to 'ObjectCache.new' (BasePart expected, got {TemplateType})`)
144
+
145
+ assert(Template:IsA("BasePart") or Template:IsA("Model"), `Invalid argument #1 to 'ObjectCache.new' (BasePart or Model expected, got {Template.ClassName})`)
146
+ assert(Template.Archivable, `ObjectCache: Cannot use template object provided, as it has Archivable set to false.`)
147
+ if Template:IsA("Model") then
148
+ assert(Template.PrimaryPart ~= nil, `Invalid Template provided to 'ObjectCache.new': Model has no PrimaryPart set!`)
149
+ end
150
+
151
+ local CacheSizeType = typeof(CacheSize)
152
+ assert(CacheSize == nil or CacheSizeType == "number", `Invalid argument #2 to 'ObjectCache.new' (number expected, got {CacheSizeType})`)
153
+ assert(CacheSize == nil or CacheSize >= 0, `Invalid argument #2 to 'ObjectCache.new' (positive number expected, got {CacheSize})`)
154
+
155
+ local ContainerType = typeof(CachesContainer)
156
+ assert(CachesContainer == nil or ContainerType == "Instance", `Invalid argument #3 to 'ObjectCache.new' (Instance expected, got {ContainerType})`)
157
+
158
+ local PreallocAmount = CacheSize or 10
159
+ local CacheParent = GetCacheContainer()
160
+
161
+ local Objects: {[BasePart]: boolean} = {}
162
+ local FreeObjects: {BasePart | Model} = table.create(PreallocAmount)
163
+
164
+ local TargetParts = table.create(PreallocAmount)
165
+
166
+ local IsTemplateModel = Template:IsA("Model")
167
+ task.spawn(function()
168
+ for Index = 1, PreallocAmount do
169
+
170
+ if Index % 100 == 0 then
171
+ RunService.Heartbeat:Wait()
172
+ end
173
+
174
+ local Object = Template:Clone()
175
+ local ObjectRoot: BasePart = if IsTemplateModel then (Object:: Model).PrimaryPart:: BasePart else Object:: BasePart
176
+
177
+ FreeObjects[Index] = Object
178
+ TargetParts[Index] = ObjectRoot
179
+
180
+ ObjectRoot.CFrame = FAR_AWAY_CFRAME;
181
+ (Object:: Instance).Parent = CacheParent
182
+ end
183
+ end)
184
+
185
+ CacheParent.Parent = CachesContainer or workspace
186
+
187
+ return setmetatable({
188
+ CacheHolder = CacheParent,
189
+ _ExpandAmount = EXPAND_BY_AMOUNT,
190
+ _Template = Template,
191
+ _FreeObjects = TargetParts,
192
+ _Objects = Objects,
193
+ _IsTemplateModel = IsTemplateModel,
194
+ _PreallocatedAmount = PreallocAmount,
195
+ }, Cache)
196
+ end
197
+
198
+ return Constructor