· 3 years ago · May 21, 2022, 07:00 PM
1--[[
2 --[ Datastore Service ]--
3 [+] Manages data for the servers!
4--]]
5--// Services
6local playerService = game:GetService("Players")
7local serverStorage = game:GetService("ServerStorage")
8local replicatedStorage = game:GetService("ReplicatedStorage")
9local dataStoreService = game:GetService("DataStoreService")
10local marketplace = game:GetService("MarketplaceService")
11local messageService = game:GetService("MessagingService")
12local chatService = require(game.ServerScriptService:WaitForChild("ChatServiceRunner").ChatService)
13local teleportService = game:GetService("TeleportService")
14local httpService = game:GetService("HttpService")
15
16--// Modules
17local modules = serverStorage:WaitForChild("Modules")
18local valmod = require(modules.CoreModules.ValueModule)
19local items = require(modules.Services.MarketService.ItemStorage)
20
21--// Storages
22local playerdatastore = dataStoreService:GetDataStore("BallOutPlayerData v.0.0.17")
23local admindatastore = dataStoreService:GetDataStore("BallOutAdminData v.0.0.02")
24local youtubedatastore = dataStoreService:GetDataStore("BallOutYoutube v.0.0.02")
25local bandatastore = dataStoreService:GetDataStore("BallOutBanData v.0.0.01")
26
27--// Default
28local defalut = require(script.DataManager)
29
30--// Data
31local adminData = admindatastore:GetAsync("Admins v.0.0.01")
32local youtubeData = youtubedatastore:GetAsync("YoutubeData v.0.0.01")
33local banData = bandatastore:GetAsync("Bans v.0.0.01")
34
35--// Checking data stores!
36if not (adminData) then
37 admindatastore:SetAsync("Admins v.0.0.01", defalut.AdminData)
38 adminData = admindatastore:GetAsync("Admins v.0.0.01")
39end
40
41if not (youtubeData) then
42 youtubedatastore:SetAsync("YoutubeData v.0.0.01", {})
43 youtubeData = youtubedatastore:GetAsync("YoutubeData v.0.0.01")
44end
45
46if not (banData) then
47 bandatastore:SetAsync("Bans v.0.0.01", {})
48 banData = bandatastore:GetAsync("Bans v.0.0.01")
49end
50
51
52--[ CLIENT ]--
53local client = replicatedStorage:WaitForChild("Communication").Client
54
55--// Game ID's
56local park = 4699691339
57local mobileOnlyPark = 5335220878
58
59--// Keys
60local dataStoreKeys = {
61 ["AdminData"] = "Admins v.0.0.01",
62 ["BansData"] = "Bans v.0.0.01",
63 ["YoutubeData"] = "YoutubeData v.0.0.01",
64}
65
66local dataTable = {
67 youtubeData = youtubeData,
68 adminData = adminData,
69}
70
71local dataStores = {
72 ["PlayerData"] = playerdatastore,
73 ["AdminData"] = admindatastore,
74 ["BansData"] = bandatastore,
75 ["YoutubeData"] = youtubedatastore,
76}
77
78local gamepasses = {
79 DoubleExp = 7111021,
80 QuadExp = 7111036,
81 NewDoubleExp = 10465070,
82 NewQuadExp = 10465075,
83}
84
85--// Structures
86local values = {
87 string = "StringValue",
88 number = "NumberValue",
89 boolean = "BoolValue"
90}
91
92
93--// Load Player Values
94local function LoadValues(player)
95 local vals = Instance.new("Configuration", player)
96 vals.Name = "values"
97
98 for VN, VV in pairs(defalut.Default.PlayerValues) do
99 local values = Instance.new(values[type(VV)], vals)
100 values.Value = VV
101 values.Name = VN
102 end
103end
104
105--// Load Player Stats
106local function LoadStats(player, data)
107 local statsfolder = Instance.new("Configuration", player)
108 statsfolder.Name = "stats"
109
110 --[ Build ]--
111 for statname, statvalue in pairs(data.stats) do
112 if (typeof(statvalue) ~= "table") then
113 local object = Instance.new(values[type(statvalue)], statsfolder)
114 object.Name = statname
115 object.Value = statvalue
116 end
117 end
118
119 --// Check
120 if (game.PlaceId == park) then
121 local parkRecord = data.stats.park
122
123 --// Load
124 for statname, statvalue in pairs(parkRecord) do
125 local object = Instance.new(values[type(statvalue)], statsfolder)
126 object.Name = statname
127 object.Value = statvalue
128 end
129 else
130 local recRecord = data.stats.rec
131
132 --// Load
133 for statname, statvalue in pairs(recRecord) do
134 local object = Instance.new(values[type(statvalue)], statsfolder)
135 object.Name = statname
136 object.Value = statvalue
137 end
138 end
139end
140
141local function GetBoost(player, stats)
142 --[ CHECK ]--
143 local doubleExp = marketplace:UserOwnsGamePassAsync(player.userId, gamepasses.DoubleExp)
144 local quadExp = marketplace:UserOwnsGamePassAsync(player.userId, gamepasses.QuadExp)
145 local newDoubleExp = marketplace:UserOwnsGamePassAsync(player.userId, gamepasses.NewDoubleExp)
146 local newQuadExp = marketplace:UserOwnsGamePassAsync(player.userId, gamepasses.NewQuadExp)
147 local boost = Instance.new("NumberValue", stats)
148 boost.Name = "boost"
149 boost.Value = 0
150
151 if (doubleExp) or (newDoubleExp) then
152 boost.Value = boost.Value + 2
153 end
154
155 if (quadExp) or (newQuadExp) then
156 boost.Value = boost.Value + 4
157 end
158
159 --// Check Boost
160 if (boost.Value < 1) then
161 boost.Value = 1
162 end
163end
164
165local function IsActive(COURT)
166 local _settings = COURT.Court.Settings
167
168 --[ CHECK ]--
169 return _settings.active.Value
170end
171
172local function GetCourt(courtName)
173 for _, obj in pairs(workspace:GetChildren()) do
174 if (obj:IsA("Model")) and (obj.Name == courtName) then
175 return obj
176 end
177 end
178end
179
180local function LoadExtraValues(player, data)
181 local playerDataKey = tostring(player.userId)
182 local isAdmin = adminData[playerDataKey]
183 local isYoutuber = youtubeData[playerDataKey]
184 local isBanned = banData[playerDataKey]
185
186 --// Check ban
187 if (isBanned) then
188 return player:Kick("You're banned!")
189 end
190
191 --// Check Admin
192 if (isAdmin) then
193 local playerGui = player:WaitForChild("PlayerGui")
194 local character = player.Character
195 local youtubeAdderUi = serverStorage.ServerPlayerAssets.YoutuberAdder:Clone()
196 local banPanelUI = serverStorage.ServerPlayerAssets.BanPanel:Clone()
197 youtubeAdderUi.Parent = playerGui
198 banPanelUI.Parent = playerGui
199
200 --// Check
201 if (character) then
202 local tag = character.Tag.Tag
203 tag.TextColor3 = Color3.fromRGB(255, 255, 60)
204 else
205 player.CharacterAdded:Connect(function(char)
206 local tag = char.Tag.Tag
207 tag.TextColor3 = Color3.fromRGB(255, 255, 60)
208 end)
209 end
210 coroutine.resume(coroutine.create(function()
211 local speaker = chatService:GetSpeaker(player.Name)
212
213 --// Wait For Speaker
214 while not (speaker) do
215 speaker = chatService:GetSpeaker(player.Name)
216 wait(0.01)
217 end
218 if not (isYoutuber) then
219 speaker:SetExtraData("Tags", {
220 {
221 TagText = "Owner",
222 TagColor = Color3.fromRGB(255, 255, 60)
223 }
224 })
225 else
226 speaker:SetExtraData("Tags", {
227 {
228 TagText = "Owner",
229 TagColor = Color3.fromRGB(255, 255, 60)
230 },
231 {
232 TagText = "Youtuber",
233 TagColor = Color3.fromRGB(147, 0, 0)
234 }
235 })
236 end
237 speaker:SetExtraData("ChatColor", Color3.fromRGB(255, 255, 60))
238 speaker:SetExtraData("NameColor", BrickColor.new("Pastel yellow").Color)
239 end))
240 end
241
242 --// Check Youtube
243 if (isYoutuber) then
244 if (isAdmin) then
245 local character = player.Character
246 local youtubeLogo = serverStorage.ServerPlayerAssets.YoutubeLogo:Clone()
247
248 --// Check
249 if (character) then
250 local tag = character.Tag.Tag
251 youtubeLogo.Parent = tag
252 else
253 player.CharacterAdded:Connect(function(char)
254 local tag = char.Tag.Tag
255 youtubeLogo.Parent = tag
256 end)
257 end
258 else
259 local character = player.Character
260 local youtubeLogo = serverStorage.ServerPlayerAssets.YoutubeLogo:Clone()
261
262 --// Check
263 if (character) then
264 local tag = character.Tag.Tag
265 tag.TextColor3 = Color3.fromRGB(147, 0, 0)
266 youtubeLogo.Parent = tag
267 else
268 player.CharacterAdded:Connect(function(char)
269 local tag = char.Tag.Tag
270 tag.TextColor3 = Color3.fromRGB(147, 0, 0)
271 youtubeLogo.Parent = tag
272 end)
273 end
274 coroutine.resume(coroutine.create(function()
275 local speaker = chatService:GetSpeaker(player.Name)
276
277 --// Wait For Speaker
278 while not (speaker) do
279 speaker = chatService:GetSpeaker(player.Name)
280 wait(0.01)
281 end
282 speaker:SetExtraData("Tags", {
283 {
284 TagText = "Youtuber",
285 TagColor = Color3.fromRGB(147, 0, 0)
286 }
287 })
288 speaker:SetExtraData("ChatColor", Color3.fromRGB(147, 0, 0))
289 speaker:SetExtraData("NameColor", BrickColor.new("Persimmon").Color)
290 end))
291 end
292
293 --// Check
294 local inventory = data.assets.inventory
295 local trails = inventory.trails
296 local ballTextures = inventory.balltextures
297
298 --// Check
299 if not (trails["Youtuber"]) then
300 print("ADDING YOUTUBER TRAIL")
301 trails["Youtuber"] = "Youtuber"
302 end
303 if not (ballTextures["Youtuber"]) then
304 print("ADDING YOUTUBER TRAIL")
305 ballTextures["Youtuber"] = "Youtuber"
306 end
307 end
308 return isYoutuber
309end
310
311--[ DATASTORE_SERVICE ]--
312local DS = {}
313
314--[ Load Data ]--
315function DS:LoadAsync(player)
316 print("LOADING PLAYER")
317 local rawdata = playerdatastore:GetAsync(player.userId) or defalut:NewData()
318 local data = defalut:CheckForUpdates(rawdata)
319
320 --[ Load Values
321 LoadExtraValues(player, data)
322 LoadStats(player, data)
323 LoadValues(player)
324
325 --[ Store ]--
326 client.Player.getdata:FireClient(player, data)
327 _G.DS[player.Name] = data
328
329 --// Create
330 coroutine.resume(coroutine.create(function()
331 --[ CONTROL_EXP ]--
332 local stats = player:WaitForChild("stats")
333 local char = player.Character
334 local levelbadge = char.Level.LevelBadge
335 local tag = char:FindFirstChild("Tag")
336
337 --// Boost
338 GetBoost(player, stats)
339 valmod:Connect(levelbadge, stats)
340 end))
341 warn(httpService:JSONEncode(data):len())
342end
343
344
345--[ Save Player Data ]--
346function DS:SaveAsync(player, isShutDown)
347 local data = _G.DS[player.Name]
348 local vals = player:FindFirstChild("values")
349 local stats = player:FindFirstChild("stats")
350
351 --[ Check ]--
352 if not (data) then
353 warn(string.format("%s's data could not found in the container!", player.Name))
354 --[ Data Exists ]--
355 else
356 --[ Save Data ]--
357 playerdatastore:UpdateAsync(player.userId, function(oldData)
358 local currentData = oldData or defalut:NewData()
359 local cachedData = data
360
361 --// Check
362 if not (isShutDown) then
363 local courtdata = _G[vals.Court.Value]
364
365 --[ Check ]--
366 if (courtdata) then
367 local court = courtdata.court
368 local getteam = courtdata.winningteam
369
370 --// Check for activity
371 if (courtdata.active.Value) then
372 stats.loses.Value = stats.loses.Value + 1
373 stats.streak.Value = 0
374 elseif (getteam) then
375 local hasWon
376
377 --// Find
378 for _, character in pairs(getteam) do
379 if (character.Name == player.Name) then
380 hasWon = character.Name
381 break
382 end
383 end
384
385 --// Check
386 if not (hasWon) then
387 stats.loses.Value = stats.loses.Value + 1
388 stats.streak.Value = 0
389 end
390 end
391 end
392 end
393
394 --[ Load ]--
395 for name, stat in pairs(currentData.stats) do
396 if (stats:FindFirstChild(name)) then
397 currentData.stats[name] = stats:FindFirstChild(name).Value
398 end
399 end
400
401 --// Check
402 if (game.PlaceId == park) or (game.PlaceId == mobileOnlyPark) then
403 local parkRecord = currentData.stats.park
404 for statName, statValue in pairs(parkRecord) do
405 parkRecord[statName] = stats:FindFirstChild(statName).Value
406 end
407 end
408
409 --// Assets
410 local cachedAssets = cachedData.assets
411 local cachedInventory = cachedAssets.inventory
412 local cachedGuiLayout = cachedAssets.guilayout
413
414 --// Update Equipped
415 for assetName, assetValue in pairs(cachedAssets) do
416 currentData.assets[assetName] = assetValue
417 end
418
419 --// Update Inventory
420 for className, classData in pairs(cachedInventory) do
421 currentData.assets.inventory[className] = classData
422 end
423
424 --// Update Layout
425 for guiName, guiPositionData in pairs(cachedGuiLayout) do
426 currentData.assets.guilayout[guiName] = guiPositionData
427 end
428
429 print("UPDATING DATA")
430 return currentData
431 end)
432 end
433 --[ Remove ]--
434 _G.DS[player.Name] = nil
435end
436
437--[ Update Custom Datastore ]--
438function DS:UpdateDatastoreAsync(DATASTORE, KEY, VALUE)
439 local data = self:GetDatastoreAsync(DATASTORE)
440 local dataStore = dataStores[DATASTORE]
441 data[KEY] = VALUE
442 dataStores[DATASTORE]:SetAsync(dataStoreKeys[DATASTORE], data)
443
444 --// Check
445 if (dataStore == youtubedatastore) then
446 youtubeData = dataStores[DATASTORE]:GetAsync(dataStoreKeys[DATASTORE], data)
447 dataTable["youtubeData"] = youtubeData
448 elseif (dataStore == admindatastore) then
449 adminData = dataStores[DATASTORE]:GetAsync(dataStoreKeys[DATASTORE], data)
450 dataTable["adminData"] = adminData
451 elseif (dataStore == bandatastore) then
452 banData = dataStores[DATASTORE]:GetAsync(dataStoreKeys[DATASTORE], data)
453 dataTable["banData"] = banData
454 end
455end
456
457function DS:GetDatastoreAsync(DATASTORE)
458 return dataStores[DATASTORE]:GetAsync(dataStoreKeys[DATASTORE]) or {}
459end
460
461function DS:GetDataTable(tableName)
462 return dataTable[tableName]
463end
464
465client.Player.save.OnServerEvent:Connect(function(player, layoutData)
466 for i, v in pairs(layoutData) do
467 print(i, unpack(v))
468 end
469 _G.DS[player.Name].assets.guilayout = layoutData
470end)
471return DS