hypixel-api-reborn 11.1.0 → 11.2.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.
Files changed (113) hide show
  1. package/.prettierrc +3 -3
  2. package/README.md +6 -4
  3. package/eslint.config.mjs +71 -0
  4. package/package.json +21 -25
  5. package/src/API/getAchievements.js +7 -0
  6. package/src/API/getBoosters.js +1 -0
  7. package/src/API/getChallenges.js +7 -0
  8. package/src/API/getGameCounts.js +1 -0
  9. package/src/API/getGuild.js +5 -4
  10. package/src/API/getGuildAchievements.js +7 -0
  11. package/src/API/getLeaderboards.js +4 -2
  12. package/src/API/getPlayer.js +2 -1
  13. package/src/API/getQuests.js +7 -0
  14. package/src/API/getRecentGames.js +6 -10
  15. package/src/API/getServerInfo.js +42 -37
  16. package/src/API/getStatus.js +2 -1
  17. package/src/API/getWatchdogStats.js +1 -0
  18. package/src/API/index.js +28 -17
  19. package/src/API/skyblock/getAuction.js +21 -0
  20. package/src/API/skyblock/{getSkyblockAuctions.js → getAuctions.js} +19 -12
  21. package/src/API/skyblock/{getSkyblockAuctionsByPlayer.js → getAuctionsByPlayer.js} +2 -2
  22. package/src/API/skyblock/{getSkyblockBazaar.js → getBazaar.js} +1 -3
  23. package/src/API/skyblock/getBingo.js +7 -0
  24. package/src/API/skyblock/getBingoByPlayer.js +14 -0
  25. package/src/API/skyblock/{getEndedSkyblockAuctions.js → getEndedAuctions.js} +1 -0
  26. package/src/API/skyblock/getFireSales.js +7 -0
  27. package/src/API/skyblock/getGovernment.js +7 -0
  28. package/src/API/skyblock/{getSkyblockMember.js → getMember.js} +10 -3
  29. package/src/API/skyblock/getMuseum.js +15 -0
  30. package/src/API/skyblock/{getSkyblockNews.js → getNews.js} +1 -0
  31. package/src/API/skyblock/{getSkyblockProfiles.js → getProfiles.js} +14 -7
  32. package/src/Client.js +127 -25
  33. package/src/Errors.js +38 -17
  34. package/src/Private/rateLimit.js +17 -13
  35. package/src/Private/requests.js +27 -16
  36. package/src/Private/updater.js +11 -8
  37. package/src/Private/uuidCache.js +23 -30
  38. package/src/Private/validate.js +33 -22
  39. package/src/index.js +9 -0
  40. package/src/structures/APIIncident.js +4 -11
  41. package/src/structures/APIStatus.js +0 -1
  42. package/src/structures/Boosters/Booster.js +14 -13
  43. package/src/structures/Color.js +93 -48
  44. package/src/structures/Game.js +4 -2
  45. package/src/structures/Guild/Guild.js +35 -48
  46. package/src/structures/Guild/GuildMember.js +8 -8
  47. package/src/structures/Guild/GuildRank.js +2 -2
  48. package/src/structures/MiniGames/Arcade.js +242 -235
  49. package/src/structures/MiniGames/ArenaBrawl.js +11 -11
  50. package/src/structures/MiniGames/BedWars.js +262 -131
  51. package/src/structures/MiniGames/BlitzSurvivalGames.js +24 -23
  52. package/src/structures/MiniGames/CopsAndCrims.js +1 -0
  53. package/src/structures/MiniGames/Duels.js +92 -33
  54. package/src/structures/MiniGames/MegaWalls.js +3 -1
  55. package/src/structures/MiniGames/MurderMystery.js +2 -2
  56. package/src/structures/MiniGames/Pit.js +230 -2
  57. package/src/structures/MiniGames/PitInventoryItem.js +43 -0
  58. package/src/structures/MiniGames/SkyWars.js +211 -195
  59. package/src/structures/MiniGames/SmashHeroes.js +37 -35
  60. package/src/structures/MiniGames/SpeedUHC.js +17 -4
  61. package/src/structures/MiniGames/TNTGames.js +1 -1
  62. package/src/structures/MiniGames/UHC.js +33 -14
  63. package/src/structures/MiniGames/WoolWars.js +6 -5
  64. package/src/structures/Pet.js +1 -1
  65. package/src/structures/Player.js +26 -121
  66. package/src/structures/PlayerCosmetics.js +67 -12
  67. package/src/structures/ServerInfo.js +1 -1
  68. package/src/structures/SkyBlock/Auctions/Auction.js +3 -1
  69. package/src/structures/SkyBlock/Auctions/AuctionInfo.js +3 -1
  70. package/src/structures/SkyBlock/Auctions/BaseAuction.js +2 -1
  71. package/src/structures/SkyBlock/Auctions/Bid.js +1 -0
  72. package/src/structures/SkyBlock/Auctions/PartialAuction.js +1 -0
  73. package/src/structures/SkyBlock/News/SkyblockNews.js +15 -15
  74. package/src/structures/SkyBlock/PlayerBingo.js +49 -0
  75. package/src/structures/SkyBlock/SkyblockInventoryItem.js +76 -32
  76. package/src/structures/SkyBlock/SkyblockMember.js +252 -289
  77. package/src/structures/SkyBlock/SkyblockMuseum.js +60 -0
  78. package/src/structures/SkyBlock/SkyblockMuseumItem.js +54 -0
  79. package/src/structures/SkyBlock/SkyblockPet.js +3 -3
  80. package/src/structures/SkyBlock/SkyblockProfile.js +37 -23
  81. package/src/structures/SkyBlock/Static/Bingo.js +101 -0
  82. package/src/structures/SkyBlock/Static/BingoData.js +45 -0
  83. package/src/structures/SkyBlock/Static/Candidate.js +40 -0
  84. package/src/structures/SkyBlock/Static/FireSale.js +55 -0
  85. package/src/structures/SkyBlock/Static/Government.js +74 -0
  86. package/src/structures/SkyBlock/Static/Perk.js +24 -0
  87. package/src/structures/Static/Achievement.js +87 -0
  88. package/src/structures/Static/AchievementTier.js +33 -0
  89. package/src/structures/Static/Achievements.js +30 -0
  90. package/src/structures/Static/Challenges.js +29 -0
  91. package/src/structures/Static/GameAchievements.js +36 -0
  92. package/src/structures/Static/GameChallenges.js +40 -0
  93. package/src/structures/Static/GameQuests.js +24 -0
  94. package/src/structures/Static/GuildAchievements.js +34 -0
  95. package/src/structures/Static/Quest.js +66 -0
  96. package/src/structures/Static/Quests.js +31 -0
  97. package/src/structures/Status.js +2 -2
  98. package/src/utils/Constants.js +384 -543
  99. package/src/utils/{guildExp.js → Guild.js} +46 -13
  100. package/src/utils/Player.js +112 -0
  101. package/src/utils/SkyblockUtils.js +448 -186
  102. package/src/utils/arrayTools.js +1 -1
  103. package/src/utils/divide.js +1 -1
  104. package/src/utils/index.js +2 -1
  105. package/src/utils/isGuildID.js +1 -1
  106. package/src/utils/oscillation.js +4 -2
  107. package/src/utils/removeSnakeCase.js +19 -8
  108. package/src/utils/rgbToHexColor.js +1 -1
  109. package/src/utils/romanize.js +35 -4
  110. package/src/utils/toUuid.js +12 -7
  111. package/src/utils/varInt.js +2 -2
  112. package/typings/index.d.ts +1246 -446
  113. package/src/utils/toIGN.js +0 -20
@@ -1,208 +1,470 @@
1
- /* eslint-disable camelcase */
1
+ /* eslint-disable jsdoc/require-jsdoc */
2
2
  const constants = require('./Constants');
3
- module.exports = {
4
- async decode(base64, isBuffer = false) {
5
- const nbt = require('prismarine-nbt');
6
- const parseNbt = require('util').promisify(nbt.parse);
7
- const buffer = isBuffer ? base64 : Buffer.from(base64, 'base64');
8
- let data = await parseNbt(buffer);
9
- data = nbt.simplify(data);
10
- const newdata = [];
11
- for (let i = 0; i < data.i.length; i++) {
12
- newdata.push(data.i[i]);
13
- }
14
- return newdata;
15
- },
16
- getLevelByXp(xp, type, levelCap) {
17
- let xpTable;
18
- switch (type) {
19
- case 'runecrafting':
20
- xpTable = constants.runecrafting_xp;
21
- break;
22
- case 'dungeons':
23
- xpTable = constants.dungeon_xp;
24
- break;
25
- case 'hotm':
26
- xpTable = constants.hotm_xp;
27
- break;
28
- default:
29
- xpTable = constants.leveling_xp;
30
- }
31
- let maxLevel = Math.max(...Object.keys(xpTable));
32
- if ((constants.skills_cap[type] ?? maxLevel) > maxLevel) {
33
- xpTable = Object.assign(constants.xp_past_50, xpTable);
34
- maxLevel = typeof levelCap === 'number' ? maxLevel + levelCap : Math.max(...Object.keys(xpTable));
35
- }
36
- if (isNaN(xp)) {
37
- return {
38
- xp: 0,
39
- level: 0,
40
- maxLevel,
41
- xpCurrent: 0,
42
- xpForNext: xpTable[1],
43
- progress: 0
44
- };
45
- }
46
- let xpTotal = 0;
47
- let level = 0;
48
- let xpForNext = 0;
49
- for (let x = 1; x <= maxLevel; x++) {
50
- if (!xpTable[x]) continue;
51
- xpTotal += xpTable[x];
52
- if (xpTotal > xp) {
53
- xpTotal -= xpTable[x];
54
- break;
55
- } else {
56
- level = x;
57
- }
58
- }
59
- const xpCurrent = Math.floor(xp - xpTotal);
60
- if (level < maxLevel) xpForNext = Math.ceil(xpTable[level + 1]);
61
- const progress = Math.floor(Math.max(0, Math.min(xpCurrent / xpForNext, 1)) * 100 * 10) / 10;
62
3
 
4
+ async function decode(base64, isBuffer = false) {
5
+ const nbt = require('prismarine-nbt');
6
+ const parseNbt = require('util').promisify(nbt.parse);
7
+ const buffer = isBuffer ? base64 : Buffer.from(base64, 'base64');
8
+ let data = await parseNbt(buffer);
9
+ data = nbt.simplify(data);
10
+ const newdata = [];
11
+ for (let i = 0; i < data.i.length; i++) {
12
+ newdata.push(data.i[i]);
13
+ }
14
+ return newdata;
15
+ }
16
+
17
+ function getLevelByXp(xp, type, levelCap) {
18
+ let xpTable;
19
+ switch (type) {
20
+ case 'runecrafting':
21
+ xpTable = constants.runecraftingXp;
22
+ break;
23
+ case 'dungeons':
24
+ xpTable = constants.dungeonXp;
25
+ break;
26
+ case 'hotm':
27
+ xpTable = constants.hotmXp;
28
+ break;
29
+ case 'social':
30
+ xpTable = constants.socialXp;
31
+ break;
32
+ default:
33
+ xpTable = constants.levelingXp;
34
+ }
35
+ let maxLevel = Math.max(...Object.keys(xpTable));
36
+ if ((constants.skillsCap[type] ?? maxLevel) > maxLevel) {
37
+ xpTable = Object.assign(constants.xpPast50, xpTable);
38
+ maxLevel = 'number' === typeof levelCap ? maxLevel + levelCap : Math.max(...Object.keys(xpTable));
39
+ }
40
+ if (isNaN(xp)) {
63
41
  return {
64
- xp,
65
- level,
42
+ xp: 0,
43
+ level: 0,
66
44
  maxLevel,
67
- xpCurrent,
68
- xpForNext,
69
- progress
45
+ xpCurrent: 0,
46
+ xpForNext: xpTable[1],
47
+ progress: 0,
48
+ cosmetic: Boolean('runecrafting' === type || 'social' === type)
70
49
  };
71
- },
72
- getLevelByAchievement(achievementLevel, type) {
73
- let xpTable = constants.leveling_xp;
74
- let maxLevel = Math.max(...Object.keys(xpTable));
75
- if (constants.skills_cap[type] > maxLevel && type in constants.skills_achievements) {
76
- xpTable = Object.assign(constants.xp_past_50, xpTable);
77
- maxLevel = Math.max(...Object.keys(xpTable));
78
- }
79
- if (isNaN(achievementLevel)) {
80
- return {
81
- xp: 0,
82
- level: 0,
83
- maxLevel,
84
- xpCurrent: 0,
85
- xpForNext: xpTable[1],
86
- progress: 0
87
- };
88
- }
89
- let xpTotal = 0;
90
- let xpForNext = 0;
91
- for (let x = 1; x <= achievementLevel; x++) {
92
- xpTotal += xpTable[x];
50
+ }
51
+ let xpTotal = 0;
52
+ let level = 0;
53
+ let xpForNext = 0;
54
+ for (let x = 1; x <= maxLevel; x++) {
55
+ if (!xpTable[x]) continue;
56
+ xpTotal += xpTable[x];
57
+ if (xpTotal > xp) {
58
+ xpTotal -= xpTable[x];
59
+ break;
60
+ } else {
61
+ level = x;
93
62
  }
94
- if (achievementLevel < maxLevel) xpForNext = Math.ceil(xpTable[achievementLevel + 1]);
63
+ }
64
+ const xpCurrent = Math.floor(xp - xpTotal);
65
+ if (level < maxLevel) xpForNext = Math.ceil(xpTable[level + 1]);
66
+ const progress = Math.floor(Math.max(0, Math.min(xpCurrent / xpForNext, 1)) * 100 * 10) / 10;
67
+
68
+ return {
69
+ xp: xp,
70
+ level: level,
71
+ maxLevel: maxLevel,
72
+ xpCurrent: xpCurrent,
73
+ xpForNext: xpForNext,
74
+ progress: progress,
75
+ cosmetic: Boolean('runecrafting' === type || 'social' === type)
76
+ };
77
+ }
78
+
79
+ function getSlayerLevel(slayer) {
80
+ if (!slayer) {
95
81
  return {
96
- xp: xpTotal,
97
- level: achievementLevel,
98
- maxLevel,
99
- xpCurrent: 0,
100
- xpForNext,
101
- progress: 0
82
+ xp: 0,
83
+ tier1: 0,
84
+ tier2: 0,
85
+ tier3: 0,
86
+ tier4: 0,
87
+ tier5: 0,
88
+ level: 0
102
89
  };
103
- },
104
- getSlayerLevel(slayer) {
105
- if (!slayer) {
106
- return {
107
- xp: 0,
108
- tier1: 0,
109
- tier2: 0,
110
- tier3: 0,
111
- tier4: 0,
112
- tier5: 0,
113
- level: 0
114
- };
90
+ }
91
+
92
+ // eslint-disable-next-line camelcase
93
+ const { claimed_levels } = slayer;
94
+ let level = 0;
95
+
96
+ // eslint-disable-next-line camelcase
97
+ for (const levelName in claimed_levels) {
98
+ if (Object.prototype.hasOwnProperty.call(claimed_levels, levelName)) {
99
+ const newLevel = parseInt(levelName.replace('_special', '').split('_').pop(), 10);
100
+ if (newLevel > level) {
101
+ level = newLevel;
102
+ }
103
+ }
104
+ }
105
+ return {
106
+ xp: slayer.xp || 0,
107
+ tier1: slayer.boss_kills_tier_0 || 0,
108
+ tier2: slayer.boss_kills_tier_1 || 0,
109
+ tier3: slayer.boss_kills_tier_2 || 0,
110
+ tier4: slayer.boss_kills_tier_3 || 0,
111
+ tier5: slayer.boss_kills_tier_4 || 0,
112
+ level
113
+ };
114
+ }
115
+
116
+ function getMemberStats(obj) {
117
+ return Object.keys(obj).reduce(
118
+ (result, currentKey) => {
119
+ const key = currentKey.replace(/_[a-z]/gi, (match) => match[1].toUpperCase());
120
+
121
+ if (currentKey.startsWith('kills') || currentKey.startsWith('deaths')) {
122
+ const category = currentKey.startsWith('kills') ? 'kills' : 'deaths';
123
+ const subKey = key === category ? 'total' : key;
124
+
125
+ result[category][
126
+ subKey.replace(category, (sub, _, key) => {
127
+ return key[sub.length].toLowerCase() + key.slice(sub.length + 1);
128
+ })
129
+ ] = obj[currentKey];
130
+ } else {
131
+ result[key] = obj[currentKey];
132
+ }
133
+
134
+ return result;
135
+ },
136
+ { kills: {}, deaths: {} }
137
+ );
138
+ }
139
+
140
+ function getTrophyFishRank(level) {
141
+ if (1 === level) {
142
+ return 'Bronze';
143
+ } else if (2 === level) {
144
+ return 'Silver';
145
+ } else if (3 === level) {
146
+ return 'Gold';
147
+ } else if (4 === level) {
148
+ return 'Diamond';
149
+ }
150
+ return 'Bronze';
151
+ }
152
+
153
+ function getSkills(data) {
154
+ const skillsObject = {};
155
+ skillsObject.combat = getLevelByXp(data?.player_data?.experience?.SKILL_COMBAT ?? 0, 'combat');
156
+ skillsObject.farming = getLevelByXp(
157
+ data?.player_data?.experience?.SKILL_FARMING ?? 0,
158
+ 'farming',
159
+ data?.m?.jacobs_contest?.perks?.farming_level_cap ?? 0 + 50
160
+ );
161
+ skillsObject.fishing = getLevelByXp(data?.player_data?.experience?.SKILL_FISHING ?? 0, 'fishing');
162
+ skillsObject.mining = getLevelByXp(data?.player_data?.experience?.SKILL_MINING ?? 0, 'mining');
163
+ skillsObject.foraging = getLevelByXp(data?.player_data?.experience?.SKILL_FORAGING ?? 0, 'foraging');
164
+ skillsObject.enchanting = getLevelByXp(data?.player_data?.experience?.SKILL_ENCHANTING ?? 0, 'enchanting');
165
+ skillsObject.alchemy = getLevelByXp(data?.player_data?.experience?.SKILL_ALCHEMY ?? 0, 'alchemy');
166
+ skillsObject.carpentry = getLevelByXp(data?.player_data?.experience?.SKILL_CARPENTRY ?? 0, 'carpentry');
167
+ skillsObject.runecrafting = getLevelByXp(data?.player_data?.experience?.SKILL_RUNECRAFTING ?? 0, 'runecrafting');
168
+ skillsObject.taming = getLevelByXp(data?.player_data?.experience?.SKILL_TAMING ?? 0, 'taming');
169
+ skillsObject.social = getLevelByXp(data?.player_data?.experience?.SKILL_SOCIAL ?? 0, 'social');
170
+ const levels = Object.values(skillsObject)
171
+ .filter((skill) => true !== skill.cosmetic)
172
+ .map((skill) => skill.level);
173
+ skillsObject.average = levels.reduce((a, b) => a + b, 0) / levels.length;
174
+ return skillsObject;
175
+ }
176
+
177
+ function formatBestiaryMobs(userProfile, mobs) {
178
+ const output = [];
179
+ for (const mob of mobs) {
180
+ const mobBracket = constants.bestiaryBrackets[mob.bracket];
181
+
182
+ const totalKills = mob.mobs.reduce((acc, cur) => {
183
+ return acc + (userProfile.bestiary.kills[cur] ?? 0);
184
+ }, 0);
185
+
186
+ const maxKills = mob.cap;
187
+ const nextTierKills = mobBracket.find((tier) => totalKills < tier && tier <= maxKills);
188
+ const tier = nextTierKills ? mobBracket.indexOf(nextTierKills) : mobBracket.indexOf(maxKills) + 1;
189
+
190
+ output.push({
191
+ tier: tier
192
+ });
193
+ }
194
+
195
+ return output;
196
+ }
197
+
198
+ function getBestiaryLevel(userProfile) {
199
+ try {
200
+ if (userProfile.bestiary?.kills === undefined) {
201
+ return null;
115
202
  }
116
- const { claimed_levels } = slayer;
117
- let level = 0;
118
- for (const level_name in claimed_levels) {
119
- if (Object.prototype.hasOwnProperty.call(claimed_levels, level_name)) {
120
- const _level = parseInt(level_name.replace('_special', '').split('_').pop(), 10);
121
- if (_level > level) {
122
- level = _level;
203
+
204
+ const output = {};
205
+ let tiersUnlocked = 0;
206
+ for (const [category, data] of Object.entries(constants.bestiary)) {
207
+ const { mobs } = data;
208
+ output[category] = {};
209
+
210
+ if ('fishing' === category) {
211
+ for (const [key, value] of Object.entries(data)) {
212
+ output[category][key] = {
213
+ mobs: formatBestiaryMobs(userProfile, value.mobs)
214
+ };
215
+ tiersUnlocked += output[category][key].mobs.reduce((acc, cur) => acc + cur.tier, 0);
123
216
  }
217
+ } else {
218
+ output[category].mobs = formatBestiaryMobs(userProfile, mobs);
219
+ tiersUnlocked += output[category].mobs.reduce((acc, cur) => acc + cur.tier, 0);
124
220
  }
125
221
  }
222
+
223
+ return tiersUnlocked / 10;
224
+ } catch (error) {
225
+ // eslint-disable-next-line no-console
226
+ console.log(error);
227
+ return null;
228
+ }
229
+ }
230
+
231
+ function getSlayer(data) {
232
+ if (!data?.slayer?.slayer_bosses) return;
233
+ return {
234
+ zombie: getSlayerLevel(data?.slayer?.slayer_bosses?.zombie),
235
+ spider: getSlayerLevel(data?.slayer?.slayer_bosses?.spider),
236
+ wolf: getSlayerLevel(data?.slayer?.slayer_bosses?.wolf),
237
+ enderman: getSlayerLevel(data?.slayer?.slayer_bosses?.enderman),
238
+ blaze: getSlayerLevel(data?.slayer?.slayer_bosses?.blaze),
239
+ vampire: getSlayerLevel(data?.slayer?.slayer_bosses?.vampire)
240
+ };
241
+ }
242
+
243
+ function getDungeons(data) {
244
+ return {
245
+ types: {
246
+ catacombs: getLevelByXp(
247
+ data.dungeons?.dungeon_types?.catacombs ? data.dungeons.dungeon_types.catacombs.experience : null,
248
+ 'dungeons'
249
+ )
250
+ },
251
+ classes: {
252
+ healer: getLevelByXp(
253
+ data.dungeons?.player_classes?.healer ? data.dungeons.player_classes.healer.experience : null,
254
+ 'dungeons'
255
+ ),
256
+ mage: getLevelByXp(
257
+ data.dungeons?.player_classes?.mage ? data.dungeons.player_classes.mage.experience : null,
258
+ 'dungeons'
259
+ ),
260
+ berserk: getLevelByXp(
261
+ data.dungeons?.player_classes?.berserk ? data.dungeons.player_classes.berserk.experience : null,
262
+ 'dungeons'
263
+ ),
264
+ archer: getLevelByXp(
265
+ data.dungeons?.player_classes?.archer ? data.dungeons.player_classes.archer.experience : null,
266
+ 'dungeons'
267
+ ),
268
+ tank: getLevelByXp(
269
+ data.dungeons?.player_classes?.tank ? data.dungeons.player_classes.tank.experience : null,
270
+ 'dungeons'
271
+ )
272
+ }
273
+ };
274
+ }
275
+
276
+ function getJacobData(data) {
277
+ if (!data.jacobs_contest) {
126
278
  return {
127
- xp: slayer.xp || 0,
128
- tier1: slayer.boss_kills_tier_0 || 0,
129
- tier2: slayer.boss_kills_tier_1 || 0,
130
- tier3: slayer.boss_kills_tier_2 || 0,
131
- tier4: slayer.boss_kills_tier_3 || 0,
132
- tier5: slayer.boss_kills_tier_4 || 0,
133
- level
279
+ medals: {
280
+ bronze: 0,
281
+ silver: 0,
282
+ gold: 0
283
+ },
284
+ perks: {
285
+ doubleDrops: 0,
286
+ farmingLevelCap: 0,
287
+ personalBests: false
288
+ },
289
+ contests: {}
134
290
  };
135
- },
136
- getSlayerLevelByXp(xp) {
137
- const { slayer_xp } = constants;
138
- const maxLevel = Math.max(...Object.keys(slayer_xp));
139
- let level = 0;
140
- for (let x = 1; x <= maxLevel && slayer_xp[x] <= xp; x++) {
141
- level = x;
142
- }
143
- return level;
144
- },
145
- getBonusStat(level, skill, max, incremention) {
146
- const skill_stats = constants.bonus_stats[skill];
147
- const steps = Object.keys(skill_stats)
148
- .sort((a, b) => Number(a) - Number(b))
149
- .map((a) => Number(a));
150
- const bonus = Object.assign({}, constants.stat_template);
151
- for (let x = steps[0]; x <= max; x += incremention) {
152
- if (level < x) {
153
- break;
154
- }
155
- const skill_step = steps
156
- .slice()
157
- .reverse()
158
- .find((a) => a <= x);
159
- const skill_bonus = skill_stats[skill_step];
160
- for (const skill in skill_bonus) {
161
- if (Object.prototype.hasOwnProperty.call(skill_bonus, skill)) {
162
- bonus[skill] += skill_bonus[skill];
291
+ }
292
+ return {
293
+ medals: data.jacobs_contest.medals_inv
294
+ ? {
295
+ bronze: data.jacobs_contest.medals_inv.bronze || 0,
296
+ silver: data.jacobs_contest.medals_inv.silver || 0,
297
+ gold: data.jacobs_contest.medals_inv.gold || 0
163
298
  }
164
- }
165
- }
166
- return bonus;
167
- },
168
- getEffectiveHealth(health, defense) {
169
- if (defense <= 0) return health;
170
- return Math.round(health * (1 + defense / 100));
171
- },
172
- getMemberStats(obj) {
173
- return Object.keys(obj).reduce(
174
- (result, currentKey) => {
175
- const key = currentKey.replace(/_[a-z]/gi, (match) => match[1].toUpperCase());
176
-
177
- if (currentKey.startsWith('kills') || currentKey.startsWith('deaths')) {
178
- const category = currentKey.startsWith('kills') ? 'kills' : 'deaths';
179
- const subKey = key === category ? 'total' : key;
180
-
181
- result[category][
182
- subKey.replace(category, (sub, _, key) => {
183
- return key[sub.length].toLowerCase() + key.slice(sub.length + 1);
184
- })
185
- ] = obj[currentKey];
186
- } else {
187
- result[key] = obj[currentKey];
299
+ : { bronze: 0, silver: 0, gold: 0 },
300
+ perks: data.jacobs_contest.perks
301
+ ? {
302
+ doubleDrops: data.jacobs_contest.perks.double_drops || 0,
303
+ farmingLevelCap: data.jacobs_contest.perks.farming_level_cap || 0,
304
+ personalBests: data.jacobs_contest.perks.personal_bests || false
188
305
  }
306
+ : { doubleDrops: 0, farmingLevelCap: 0, personalBests: false },
307
+ contests: data.jacobs_contest.contests || {}
308
+ };
309
+ }
189
310
 
190
- return result;
311
+ function getChocolateFactory(data) {
312
+ if (!data?.events?.easter) {
313
+ return {
314
+ employees: {
315
+ bro: 0,
316
+ cousin: 0,
317
+ sis: 0,
318
+ father: 0,
319
+ grandma: 0,
320
+ dog: 0,
321
+ uncle: 0
322
+ },
323
+ chocolate: {
324
+ current: 0,
325
+ total: 0,
326
+ sincePrestige: 0
327
+ },
328
+ timeTower: {
329
+ charges: 0,
330
+ level: 0
331
+ },
332
+ upgrades: {
333
+ click: 0,
334
+ multiplier: 0,
335
+ rabbitRarity: 0
336
+ },
337
+ goldenClick: {
338
+ amount: 0,
339
+ year: 0
191
340
  },
192
- { kills: {}, deaths: {} }
193
- );
194
- },
195
- getTrophyFishRank(level) {
196
- if (level === 1) {
197
- return 'Bronze';
198
- } else if (level === 2) {
199
- return 'Silver';
200
- } else if (level === 3) {
201
- return 'Gold';
202
- } else if (level === 4) {
203
- return 'Diamond';
341
+ barnCapacity: 0,
342
+ prestige: 0
343
+ };
344
+ }
345
+ return {
346
+ employees: {
347
+ bro: data?.events?.easter?.employees?.rabbit_bro || 0,
348
+ cousin: data?.events?.easter?.employees?.rabbit_cousin || 0,
349
+ sis: data?.events?.easter?.employees?.rabbit_sis || 0,
350
+ father: data?.events?.easter?.employees?.rabbit_father || 0,
351
+ grandma: data?.events?.easter?.employees?.rabbit_grandma || 0,
352
+ dog: data?.events?.easter?.employees?.rabbit_dog || 0,
353
+ uncle: data?.events?.easter?.employees?.rabbit_uncle || 0
354
+ },
355
+ chocolate: {
356
+ current: data?.events?.easter?.chocolate || 0,
357
+ total: data?.events?.easter?.total_chocolate || 0,
358
+ sincePrestige: data?.events?.easter?.chocolate_since_prestige || 0
359
+ },
360
+ timeTower: {
361
+ charges: data?.events?.easter?.time_tower?.charges || 0,
362
+ level: data?.events?.easter?.time_tower?.level || 0
363
+ },
364
+ upgrades: {
365
+ click: data?.events?.easter?.click_upgrades || 0,
366
+ multiplier: data?.events?.easter?.chocolate_multiplier_upgrades || 0,
367
+ rabbitRarity: data?.events?.easter?.rabbit_rarity_upgrades || 0
368
+ },
369
+ goldenClick: {
370
+ amount: data?.events?.easter?.golden_click_amount || 0,
371
+ year: data?.events?.easter?.golden_click_year || 0
372
+ },
373
+ barnCapacity: data?.events?.easter?.rabbit_barn_capacity_level || 0,
374
+ prestige: data?.events?.easter?.chocolate_level || 0
375
+ };
376
+ }
377
+
378
+ function getPetLevel(petExp, offsetRarity, maxLevel) {
379
+ const rarityOffset = constants.petRarityOffset[offsetRarity];
380
+ const levels = constants.petLevels.slice(rarityOffset, rarityOffset + maxLevel - 1);
381
+
382
+ const xpMaxLevel = levels.reduce((a, b) => a + b, 0);
383
+ let xpTotal = 0;
384
+ let level = 1;
385
+
386
+ let xpForNext;
387
+
388
+ for (let i = 0; i < maxLevel; i++) {
389
+ xpTotal += levels[i];
390
+
391
+ if (xpTotal > petExp) {
392
+ xpTotal -= levels[i];
393
+ break;
204
394
  } else {
205
- return 'Bronze';
395
+ level++;
206
396
  }
207
397
  }
398
+
399
+ let xpCurrent = Math.floor(petExp - xpTotal);
400
+ let progress;
401
+
402
+ if (level < maxLevel) {
403
+ xpForNext = Math.ceil(levels[level - 1]);
404
+ progress = Math.max(0, Math.min(xpCurrent / xpForNext, 1));
405
+ } else {
406
+ level = maxLevel;
407
+ xpCurrent = petExp - levels[maxLevel - 1];
408
+ xpForNext = 0;
409
+ progress = 1;
410
+ }
411
+
412
+ return {
413
+ level,
414
+ xpCurrent,
415
+ xpForNext,
416
+ progress,
417
+ xpMaxLevel
418
+ };
419
+ }
420
+
421
+ function parseRarity(stringContainingRarity) {
422
+ const rarityArray = [
423
+ 'COMMON',
424
+ 'UNCOMMON',
425
+ 'RARE',
426
+ 'EPIC',
427
+ 'LEGENDARY',
428
+ 'MYTHIC',
429
+ 'DIVINE',
430
+ 'SPECIAL',
431
+ 'VERY SPECIAL'
432
+ ];
433
+ for (const rarity of rarityArray) {
434
+ if (stringContainingRarity.includes(rarity)) return rarity;
435
+ }
436
+ }
437
+
438
+ function parseGearScore(lore) {
439
+ for (const line of lore) {
440
+ if (line.match(/Gear Score: §[0-9a-f](\d+)/)) return Number(line.match(/Gear Score: §d(\d+)/)[1]);
441
+ }
442
+ }
443
+
444
+ function populateGoals(achieved, all) {
445
+ const populatedAchieved = [];
446
+ const unachieved = [];
447
+ for (const goal of all) {
448
+ if (achieved.find((str) => str === goal.name)) populatedAchieved.push(goal);
449
+ else unachieved.push(goal);
450
+ }
451
+ populatedAchieved.unachievedGoals = unachieved;
452
+ return populatedAchieved;
453
+ }
454
+
455
+ module.exports = {
456
+ decode,
457
+ getLevelByXp,
458
+ getMemberStats,
459
+ getTrophyFishRank,
460
+ getSkills,
461
+ getBestiaryLevel,
462
+ getSlayer,
463
+ getDungeons,
464
+ getJacobData,
465
+ getChocolateFactory,
466
+ getPetLevel,
467
+ parseRarity,
468
+ parseGearScore,
469
+ populateGoals
208
470
  };
@@ -1,4 +1,4 @@
1
1
  module.exports = {
2
- isStrArray: (input) => Array.isArray(input) || typeof input === 'string',
2
+ isStrArray: (input) => Array.isArray(input) || 'string' === typeof input,
3
3
  strToArray: (input) => [input].flat()
4
4
  };
@@ -1,5 +1,5 @@
1
1
  module.exports = (a = 0, b = 1) => {
2
- const out = +((a || 0) / (b || 0)).toFixed(2) || 0;
2
+ const out = Number(((a || 0) / (b || 0)).toFixed(2)) || 0;
3
3
  if (isFinite(out)) return out;
4
4
  return a;
5
5
  };
@@ -2,12 +2,13 @@ module.exports = {
2
2
  arrayTool: require('./arrayTools'),
3
3
  Constants: require('./Constants'),
4
4
  divide: require('./divide'),
5
+ guild: require('./Guild'),
5
6
  isGuildID: require('./isGuildID'),
6
7
  isUUID: require('./isUUID'),
7
8
  oscillation: require('./oscillation'),
9
+ player: require('./Player'),
8
10
  removeSnakeCase: require('./removeSnakeCase'),
9
11
  SkyblockUtils: require('./SkyblockUtils'),
10
- toIGN: require('./toIGN'),
11
12
  toUuid: require('./toUuid'),
12
13
  varInt: require('./varInt')
13
14
  };
@@ -1,3 +1,3 @@
1
1
  module.exports = (id) => {
2
- return id.length === 24;
2
+ return 24 === id.length;
3
3
  };