@takaro/modules 0.0.13 ā 0.0.15
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/dist/main.js +2 -0
- package/dist/main.js.map +1 -1
- package/dist/modules/dailyRewards/commands/daily.d.ts +1 -0
- package/dist/modules/dailyRewards/commands/daily.js +106 -0
- package/dist/modules/dailyRewards/commands/daily.js.map +1 -0
- package/dist/modules/dailyRewards/commands/streak.d.ts +1 -0
- package/dist/modules/dailyRewards/commands/streak.js +34 -0
- package/dist/modules/dailyRewards/commands/streak.js.map +1 -0
- package/dist/modules/dailyRewards/commands/topstreak.d.ts +1 -0
- package/dist/modules/dailyRewards/commands/topstreak.js +44 -0
- package/dist/modules/dailyRewards/commands/topstreak.js.map +1 -0
- package/dist/modules/dailyRewards/functions/utils.d.ts +5 -0
- package/dist/modules/dailyRewards/functions/utils.js +32 -0
- package/dist/modules/dailyRewards/functions/utils.js.map +1 -0
- package/dist/modules/dailyRewards/hooks/dailyLoginCheck.d.ts +1 -0
- package/dist/modules/dailyRewards/hooks/dailyLoginCheck.js +19 -0
- package/dist/modules/dailyRewards/hooks/dailyLoginCheck.js.map +1 -0
- package/dist/modules/dailyRewards/index.d.ts +4 -0
- package/dist/modules/dailyRewards/index.js +117 -0
- package/dist/modules/dailyRewards/index.js.map +1 -0
- package/dist/modules/economyUtils/commands/shop.js +6 -6
- package/dist/modules/economyUtils/commands/shop.js.map +1 -1
- package/dist/modules/economyUtils/cronJobs/zombieKillReward.d.ts +1 -0
- package/dist/modules/economyUtils/cronJobs/zombieKillReward.js +66 -0
- package/dist/modules/economyUtils/cronJobs/zombieKillReward.js.map +1 -0
- package/dist/modules/economyUtils/index.js +21 -2
- package/dist/modules/economyUtils/index.js.map +1 -1
- package/dist/modules/geoBlock/hooks/IPDetected.js +4 -2
- package/dist/modules/geoBlock/hooks/IPDetected.js.map +1 -1
- package/dist/modules/gimme/commands/gimme.js +17 -6
- package/dist/modules/gimme/commands/gimme.js.map +1 -1
- package/dist/modules/gimme/index.js +23 -2
- package/dist/modules/gimme/index.js.map +1 -1
- package/dist/modules/playerOnboarding/commands/starterkit.js +16 -3
- package/dist/modules/playerOnboarding/commands/starterkit.js.map +1 -1
- package/dist/modules/playerOnboarding/index.js +24 -3
- package/dist/modules/playerOnboarding/index.js.map +1 -1
- package/dist/modules.json +88 -11
- package/package.json +1 -1
- package/scripts/buildBuiltinJson.ts +46 -2
- package/src/__tests__/economy/shop.integration.test.ts +23 -0
- package/src/__tests__/economy/zombieKillReward.integration.test.ts +296 -0
- package/src/__tests__/gimme.integration.test.ts +8 -2
- package/src/__tests__/onboarding.integration.test.ts +23 -20
- package/src/main.ts +2 -0
- package/src/modules/dailyRewards/commands/daily.js +118 -0
- package/src/modules/dailyRewards/commands/streak.js +42 -0
- package/src/modules/dailyRewards/commands/topstreak.js +54 -0
- package/src/modules/dailyRewards/functions/utils.js +36 -0
- package/src/modules/dailyRewards/hooks/dailyLoginCheck.js +24 -0
- package/src/modules/dailyRewards/index.ts +126 -0
- package/src/modules/economyUtils/commands/shop.js +6 -6
- package/src/modules/economyUtils/cronJobs/zombieKillReward.js +82 -0
- package/src/modules/economyUtils/index.ts +23 -2
- package/src/modules/geoBlock/hooks/IPDetected.js +4 -2
- package/src/modules/gimme/commands/gimme.js +16 -6
- package/src/modules/gimme/index.ts +23 -2
- package/src/modules/playerOnboarding/commands/starterkit.js +19 -5
- package/src/modules/playerOnboarding/index.ts +24 -3
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { EventsAwaiter, expect, IntegrationTest, IShopSetup, shopSetup } from '@takaro/test';
|
|
2
|
+
import { HookEvents } from '../../dto/index.js';
|
|
3
|
+
import { Client, PlayerOutputDTO } from '@takaro/apiclient';
|
|
4
|
+
|
|
5
|
+
const group = 'EconomyUtils:ZombieKillReward';
|
|
6
|
+
|
|
7
|
+
async function triggerKills(client: Client, player: PlayerOutputDTO, gameServerId: string, count: number) {
|
|
8
|
+
const events = (await new EventsAwaiter().connect(client)).waitForEvents(HookEvents.ENTITY_KILLED, count);
|
|
9
|
+
|
|
10
|
+
if (!player.playerOnGameServers) throw new Error('Player has no pogs');
|
|
11
|
+
const pog = player.playerOnGameServers.find((pog) => pog.gameServerId === gameServerId);
|
|
12
|
+
if (!pog) throw new Error('Player not found on game server');
|
|
13
|
+
|
|
14
|
+
await Promise.all(
|
|
15
|
+
Array.from({ length: count }, () => {
|
|
16
|
+
return client.gameserver.gameServerControllerExecuteCommand(gameServerId, {
|
|
17
|
+
command: `triggerKill ${pog.gameId}`,
|
|
18
|
+
});
|
|
19
|
+
}),
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
await events;
|
|
23
|
+
return events;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const tests = [
|
|
27
|
+
new IntegrationTest<IShopSetup>({
|
|
28
|
+
group,
|
|
29
|
+
snapshot: false,
|
|
30
|
+
setup: shopSetup,
|
|
31
|
+
name: 'Simple happy path, killing one zombie gives one currency',
|
|
32
|
+
test: async function () {
|
|
33
|
+
const pogBefore = (
|
|
34
|
+
await this.client.playerOnGameserver.playerOnGameServerControllerGetOne(
|
|
35
|
+
this.setupData.gameserver.id,
|
|
36
|
+
this.setupData.players[0].id,
|
|
37
|
+
)
|
|
38
|
+
).data.data;
|
|
39
|
+
|
|
40
|
+
(
|
|
41
|
+
await this.client.gameserver.gameServerControllerInstallModule(
|
|
42
|
+
this.setupData.gameserver.id,
|
|
43
|
+
this.setupData.economyUtilsModule.id,
|
|
44
|
+
)
|
|
45
|
+
).data.data;
|
|
46
|
+
const zombieKillCronjob = this.setupData.economyUtilsModule.cronJobs.find(
|
|
47
|
+
(cronjob) => cronjob.name === 'zombieKillReward',
|
|
48
|
+
);
|
|
49
|
+
if (!zombieKillCronjob) throw new Error('Cronjob not found');
|
|
50
|
+
await triggerKills(this.client, this.setupData.players[0], this.setupData.gameserver.id, 1);
|
|
51
|
+
await this.client.cronjob.cronJobControllerTrigger({
|
|
52
|
+
gameServerId: this.setupData.gameserver.id,
|
|
53
|
+
moduleId: this.setupData.economyUtilsModule.id,
|
|
54
|
+
cronjobId: zombieKillCronjob.id,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.CRONJOB_EXECUTED, 1);
|
|
58
|
+
await events;
|
|
59
|
+
|
|
60
|
+
const pogAfter = (
|
|
61
|
+
await this.client.playerOnGameserver.playerOnGameServerControllerGetOne(
|
|
62
|
+
this.setupData.gameserver.id,
|
|
63
|
+
this.setupData.players[0].id,
|
|
64
|
+
)
|
|
65
|
+
).data.data;
|
|
66
|
+
expect(pogAfter.currency).to.equal(pogBefore.currency + 1);
|
|
67
|
+
},
|
|
68
|
+
}),
|
|
69
|
+
/**
|
|
70
|
+
* First kill 3 zombies, then trigger the cronjob
|
|
71
|
+
* Check if the player has 3 currency
|
|
72
|
+
* Then kill 4 zombies
|
|
73
|
+
* Check if the player has 7 currency
|
|
74
|
+
*/
|
|
75
|
+
new IntegrationTest<IShopSetup>({
|
|
76
|
+
group,
|
|
77
|
+
snapshot: false,
|
|
78
|
+
setup: shopSetup,
|
|
79
|
+
name: 'Killing multiple zombies',
|
|
80
|
+
test: async function () {
|
|
81
|
+
const pogBefore = (
|
|
82
|
+
await this.client.playerOnGameserver.playerOnGameServerControllerGetOne(
|
|
83
|
+
this.setupData.gameserver.id,
|
|
84
|
+
this.setupData.players[0].id,
|
|
85
|
+
)
|
|
86
|
+
).data.data;
|
|
87
|
+
|
|
88
|
+
(
|
|
89
|
+
await this.client.gameserver.gameServerControllerInstallModule(
|
|
90
|
+
this.setupData.gameserver.id,
|
|
91
|
+
this.setupData.economyUtilsModule.id,
|
|
92
|
+
)
|
|
93
|
+
).data.data;
|
|
94
|
+
const zombieKillCronjob = this.setupData.economyUtilsModule.cronJobs.find(
|
|
95
|
+
(cronjob) => cronjob.name === 'zombieKillReward',
|
|
96
|
+
);
|
|
97
|
+
if (!zombieKillCronjob) throw new Error('Cronjob not found');
|
|
98
|
+
await triggerKills(this.client, this.setupData.players[0], this.setupData.gameserver.id, 3);
|
|
99
|
+
await this.client.cronjob.cronJobControllerTrigger({
|
|
100
|
+
gameServerId: this.setupData.gameserver.id,
|
|
101
|
+
moduleId: this.setupData.economyUtilsModule.id,
|
|
102
|
+
cronjobId: zombieKillCronjob.id,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.CRONJOB_EXECUTED, 1);
|
|
106
|
+
await events;
|
|
107
|
+
|
|
108
|
+
let pogAfter = (
|
|
109
|
+
await this.client.playerOnGameserver.playerOnGameServerControllerGetOne(
|
|
110
|
+
this.setupData.gameserver.id,
|
|
111
|
+
this.setupData.players[0].id,
|
|
112
|
+
)
|
|
113
|
+
).data.data;
|
|
114
|
+
expect(pogAfter.currency).to.equal(pogBefore.currency + 3);
|
|
115
|
+
|
|
116
|
+
await triggerKills(this.client, this.setupData.players[0], this.setupData.gameserver.id, 4);
|
|
117
|
+
await this.client.cronjob.cronJobControllerTrigger({
|
|
118
|
+
gameServerId: this.setupData.gameserver.id,
|
|
119
|
+
moduleId: this.setupData.economyUtilsModule.id,
|
|
120
|
+
cronjobId: zombieKillCronjob.id,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const events2 = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.CRONJOB_EXECUTED, 1);
|
|
124
|
+
await events2;
|
|
125
|
+
|
|
126
|
+
pogAfter = (
|
|
127
|
+
await this.client.playerOnGameserver.playerOnGameServerControllerGetOne(
|
|
128
|
+
this.setupData.gameserver.id,
|
|
129
|
+
this.setupData.players[0].id,
|
|
130
|
+
)
|
|
131
|
+
).data.data;
|
|
132
|
+
expect(pogAfter.currency).to.equal(pogBefore.currency + 7);
|
|
133
|
+
},
|
|
134
|
+
}),
|
|
135
|
+
new IntegrationTest<IShopSetup>({
|
|
136
|
+
group,
|
|
137
|
+
snapshot: false,
|
|
138
|
+
setup: shopSetup,
|
|
139
|
+
name: 'Different players killing zombies assigns the right amount to the right players',
|
|
140
|
+
test: async function () {
|
|
141
|
+
const pogBefore1 = (
|
|
142
|
+
await this.client.playerOnGameserver.playerOnGameServerControllerGetOne(
|
|
143
|
+
this.setupData.gameserver.id,
|
|
144
|
+
this.setupData.players[0].id,
|
|
145
|
+
)
|
|
146
|
+
).data.data;
|
|
147
|
+
const pogBefore2 = (
|
|
148
|
+
await this.client.playerOnGameserver.playerOnGameServerControllerGetOne(
|
|
149
|
+
this.setupData.gameserver.id,
|
|
150
|
+
this.setupData.players[1].id,
|
|
151
|
+
)
|
|
152
|
+
).data.data;
|
|
153
|
+
|
|
154
|
+
(
|
|
155
|
+
await this.client.gameserver.gameServerControllerInstallModule(
|
|
156
|
+
this.setupData.gameserver.id,
|
|
157
|
+
this.setupData.economyUtilsModule.id,
|
|
158
|
+
)
|
|
159
|
+
).data.data;
|
|
160
|
+
const zombieKillCronjob = this.setupData.economyUtilsModule.cronJobs.find(
|
|
161
|
+
(cronjob) => cronjob.name === 'zombieKillReward',
|
|
162
|
+
);
|
|
163
|
+
if (!zombieKillCronjob) throw new Error('Cronjob not found');
|
|
164
|
+
await triggerKills(this.client, this.setupData.players[0], this.setupData.gameserver.id, 3);
|
|
165
|
+
await triggerKills(this.client, this.setupData.players[1], this.setupData.gameserver.id, 4);
|
|
166
|
+
await this.client.cronjob.cronJobControllerTrigger({
|
|
167
|
+
gameServerId: this.setupData.gameserver.id,
|
|
168
|
+
moduleId: this.setupData.economyUtilsModule.id,
|
|
169
|
+
cronjobId: zombieKillCronjob.id,
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.CRONJOB_EXECUTED, 1);
|
|
173
|
+
await events;
|
|
174
|
+
|
|
175
|
+
const pogAfter1 = (
|
|
176
|
+
await this.client.playerOnGameserver.playerOnGameServerControllerGetOne(
|
|
177
|
+
this.setupData.gameserver.id,
|
|
178
|
+
this.setupData.players[0].id,
|
|
179
|
+
)
|
|
180
|
+
).data.data;
|
|
181
|
+
const pogAfter2 = (
|
|
182
|
+
await this.client.playerOnGameserver.playerOnGameServerControllerGetOne(
|
|
183
|
+
this.setupData.gameserver.id,
|
|
184
|
+
this.setupData.players[1].id,
|
|
185
|
+
)
|
|
186
|
+
).data.data;
|
|
187
|
+
expect(pogAfter1.currency).to.equal(pogBefore1.currency + 3);
|
|
188
|
+
expect(pogAfter2.currency).to.equal(pogBefore2.currency + 4);
|
|
189
|
+
},
|
|
190
|
+
}),
|
|
191
|
+
new IntegrationTest<IShopSetup>({
|
|
192
|
+
group,
|
|
193
|
+
snapshot: false,
|
|
194
|
+
setup: shopSetup,
|
|
195
|
+
name: 'Can configure a custom amount of currency per kill',
|
|
196
|
+
test: async function () {
|
|
197
|
+
const pogBefore = (
|
|
198
|
+
await this.client.playerOnGameserver.playerOnGameServerControllerGetOne(
|
|
199
|
+
this.setupData.gameserver.id,
|
|
200
|
+
this.setupData.players[0].id,
|
|
201
|
+
)
|
|
202
|
+
).data.data;
|
|
203
|
+
(
|
|
204
|
+
await this.client.gameserver.gameServerControllerInstallModule(
|
|
205
|
+
this.setupData.gameserver.id,
|
|
206
|
+
this.setupData.economyUtilsModule.id,
|
|
207
|
+
{
|
|
208
|
+
userConfig: JSON.stringify({ zombieKillReward: 5 }),
|
|
209
|
+
},
|
|
210
|
+
)
|
|
211
|
+
).data.data;
|
|
212
|
+
const zombieKillCronjob = this.setupData.economyUtilsModule.cronJobs.find(
|
|
213
|
+
(cronjob) => cronjob.name === 'zombieKillReward',
|
|
214
|
+
);
|
|
215
|
+
if (!zombieKillCronjob) throw new Error('Cronjob not found');
|
|
216
|
+
await triggerKills(this.client, this.setupData.players[0], this.setupData.gameserver.id, 1);
|
|
217
|
+
await this.client.cronjob.cronJobControllerTrigger({
|
|
218
|
+
gameServerId: this.setupData.gameserver.id,
|
|
219
|
+
moduleId: this.setupData.economyUtilsModule.id,
|
|
220
|
+
cronjobId: zombieKillCronjob.id,
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.CRONJOB_EXECUTED, 1);
|
|
224
|
+
await events;
|
|
225
|
+
|
|
226
|
+
const pogAfter = (
|
|
227
|
+
await this.client.playerOnGameserver.playerOnGameServerControllerGetOne(
|
|
228
|
+
this.setupData.gameserver.id,
|
|
229
|
+
this.setupData.players[0].id,
|
|
230
|
+
)
|
|
231
|
+
).data.data;
|
|
232
|
+
expect(pogAfter.currency).to.equal(pogBefore.currency + 5);
|
|
233
|
+
},
|
|
234
|
+
}),
|
|
235
|
+
new IntegrationTest<IShopSetup>({
|
|
236
|
+
group,
|
|
237
|
+
snapshot: false,
|
|
238
|
+
setup: shopSetup,
|
|
239
|
+
name: 'Can override amount earned per role',
|
|
240
|
+
test: async function () {
|
|
241
|
+
const zombieKillEarnerPermission = await this.client.permissionCodesToInputs(['ZOMBIE_KILL_REWARD_OVERRIDE']);
|
|
242
|
+
await this.client.role.roleControllerUpdate(this.setupData.role.id, {
|
|
243
|
+
permissions: [
|
|
244
|
+
{
|
|
245
|
+
permissionId: zombieKillEarnerPermission[0].permissionId,
|
|
246
|
+
count: 3,
|
|
247
|
+
},
|
|
248
|
+
],
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
const pogBefore = (
|
|
252
|
+
await this.client.playerOnGameserver.playerOnGameServerControllerGetOne(
|
|
253
|
+
this.setupData.gameserver.id,
|
|
254
|
+
this.setupData.players[0].id,
|
|
255
|
+
)
|
|
256
|
+
).data.data;
|
|
257
|
+
(
|
|
258
|
+
await this.client.gameserver.gameServerControllerInstallModule(
|
|
259
|
+
this.setupData.gameserver.id,
|
|
260
|
+
this.setupData.economyUtilsModule.id,
|
|
261
|
+
{
|
|
262
|
+
userConfig: JSON.stringify({ zombieKillReward: 5 }),
|
|
263
|
+
},
|
|
264
|
+
)
|
|
265
|
+
).data.data;
|
|
266
|
+
|
|
267
|
+
const zombieKillCronjob = this.setupData.economyUtilsModule.cronJobs.find(
|
|
268
|
+
(cronjob) => cronjob.name === 'zombieKillReward',
|
|
269
|
+
);
|
|
270
|
+
if (!zombieKillCronjob) throw new Error('Cronjob not found');
|
|
271
|
+
await triggerKills(this.client, this.setupData.players[0], this.setupData.gameserver.id, 1);
|
|
272
|
+
await this.client.cronjob.cronJobControllerTrigger({
|
|
273
|
+
gameServerId: this.setupData.gameserver.id,
|
|
274
|
+
moduleId: this.setupData.economyUtilsModule.id,
|
|
275
|
+
cronjobId: zombieKillCronjob.id,
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.CRONJOB_EXECUTED, 1);
|
|
279
|
+
await events;
|
|
280
|
+
|
|
281
|
+
const pogAfter = (
|
|
282
|
+
await this.client.playerOnGameserver.playerOnGameServerControllerGetOne(
|
|
283
|
+
this.setupData.gameserver.id,
|
|
284
|
+
this.setupData.players[0].id,
|
|
285
|
+
)
|
|
286
|
+
).data.data;
|
|
287
|
+
expect(pogAfter.currency).to.equal(pogBefore.currency + 3);
|
|
288
|
+
},
|
|
289
|
+
}),
|
|
290
|
+
];
|
|
291
|
+
|
|
292
|
+
describe(group, function () {
|
|
293
|
+
tests.forEach((test) => {
|
|
294
|
+
test.run();
|
|
295
|
+
});
|
|
296
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { IntegrationTest, expect, IModuleTestsSetupData, modulesTestSetup, EventsAwaiter } from '@takaro/test';
|
|
2
2
|
import { GameEvents } from '../dto/index.js';
|
|
3
|
+
import { faker } from '@faker-js/faker';
|
|
3
4
|
|
|
4
5
|
const group = 'gimme suite';
|
|
5
6
|
|
|
@@ -10,12 +11,17 @@ const tests = [
|
|
|
10
11
|
setup: modulesTestSetup,
|
|
11
12
|
name: 'Can give an item to a player',
|
|
12
13
|
test: async function () {
|
|
14
|
+
const items = (await this.client.item.itemControllerSearch()).data.data;
|
|
13
15
|
await this.client.gameserver.gameServerControllerInstallModule(
|
|
14
16
|
this.setupData.gameserver.id,
|
|
15
17
|
this.setupData.gimmeModule.id,
|
|
16
18
|
{
|
|
17
19
|
userConfig: JSON.stringify({
|
|
18
|
-
items:
|
|
20
|
+
items: items.map((item) => ({
|
|
21
|
+
item: item.id,
|
|
22
|
+
amount: faker.number.int({ min: 1, max: 10 }),
|
|
23
|
+
quality: faker.number.int({ min: 1, max: 6 }).toString(),
|
|
24
|
+
})),
|
|
19
25
|
commands: [],
|
|
20
26
|
}),
|
|
21
27
|
},
|
|
@@ -28,7 +34,7 @@ const tests = [
|
|
|
28
34
|
});
|
|
29
35
|
|
|
30
36
|
expect((await events).length).to.be.eq(1);
|
|
31
|
-
expect((await events)[0].data.meta.msg).to.match(/You received
|
|
37
|
+
expect((await events)[0].data.meta.msg).to.match(/You received \dx \w/);
|
|
32
38
|
},
|
|
33
39
|
}),
|
|
34
40
|
/* new IntegrationTest<IModuleTestsSetupData>({
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { IntegrationTest, expect, IModuleTestsSetupData, modulesTestSetup, EventsAwaiter } from '@takaro/test';
|
|
2
|
-
import {
|
|
2
|
+
import { GameEvents } from '../dto/gameEvents.js';
|
|
3
3
|
import { HookEvents } from '../main.js';
|
|
4
|
+
import { faker } from '@faker-js/faker';
|
|
4
5
|
|
|
5
6
|
const group = 'Onboarding';
|
|
6
7
|
const groupStarterkit = 'Onboarding - Starterkit';
|
|
7
8
|
|
|
8
|
-
const
|
|
9
|
+
const tests = [
|
|
9
10
|
new IntegrationTest<IModuleTestsSetupData>({
|
|
10
11
|
group,
|
|
11
12
|
snapshot: false,
|
|
@@ -16,21 +17,14 @@ const _tests = [
|
|
|
16
17
|
this.setupData.gameserver.id,
|
|
17
18
|
this.setupData.onboardingModule.id,
|
|
18
19
|
);
|
|
19
|
-
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE);
|
|
20
|
-
await this.client.
|
|
21
|
-
|
|
22
|
-
playerId: this.setupData.players[0].id,
|
|
23
|
-
eventType: GameEvents.PLAYER_CONNECTED,
|
|
24
|
-
eventMeta: new EventPlayerConnected({
|
|
25
|
-
player: {
|
|
26
|
-
gameId: '1',
|
|
27
|
-
},
|
|
28
|
-
msg: 'Player connected',
|
|
29
|
-
}),
|
|
20
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 5);
|
|
21
|
+
await this.client.gameserver.gameServerControllerExecuteCommand(this.setupData.gameserver.id, {
|
|
22
|
+
command: 'connectAll',
|
|
30
23
|
});
|
|
31
24
|
|
|
32
|
-
expect((await events).length).to.be.eq(
|
|
33
|
-
|
|
25
|
+
expect((await events).length).to.be.eq(5);
|
|
26
|
+
// Expect all messages to match
|
|
27
|
+
expect((await events).every((event) => event.data.meta.msg.match(/Welcome .+ to the server!/))).to.be.true;
|
|
34
28
|
},
|
|
35
29
|
}),
|
|
36
30
|
new IntegrationTest<IModuleTestsSetupData>({
|
|
@@ -39,12 +33,17 @@ const _tests = [
|
|
|
39
33
|
setup: modulesTestSetup,
|
|
40
34
|
name: 'Starterkit command gives the player items',
|
|
41
35
|
test: async function () {
|
|
36
|
+
const items = (await this.client.item.itemControllerSearch()).data.data;
|
|
42
37
|
await this.client.gameserver.gameServerControllerInstallModule(
|
|
43
38
|
this.setupData.gameserver.id,
|
|
44
39
|
this.setupData.onboardingModule.id,
|
|
45
40
|
{
|
|
46
41
|
userConfig: JSON.stringify({
|
|
47
|
-
starterKitItems:
|
|
42
|
+
starterKitItems: items.map((item) => ({
|
|
43
|
+
item: item.id,
|
|
44
|
+
amount: faker.number.int({ min: 1, max: 6 }),
|
|
45
|
+
quality: faker.number.int({ min: 1, max: 6 }).toString(),
|
|
46
|
+
})),
|
|
48
47
|
}),
|
|
49
48
|
},
|
|
50
49
|
);
|
|
@@ -64,12 +63,17 @@ const _tests = [
|
|
|
64
63
|
setup: modulesTestSetup,
|
|
65
64
|
name: 'Starterkit command can only be used once',
|
|
66
65
|
test: async function () {
|
|
66
|
+
const items = (await this.client.item.itemControllerSearch()).data.data;
|
|
67
67
|
await this.client.gameserver.gameServerControllerInstallModule(
|
|
68
68
|
this.setupData.gameserver.id,
|
|
69
69
|
this.setupData.onboardingModule.id,
|
|
70
70
|
{
|
|
71
71
|
userConfig: JSON.stringify({
|
|
72
|
-
starterKitItems:
|
|
72
|
+
starterKitItems: items.map((item) => ({
|
|
73
|
+
item: item.id,
|
|
74
|
+
amount: faker.number.int({ min: 1, max: 6 }),
|
|
75
|
+
quality: faker.number.int({ min: 1, max: 6 }).toString(),
|
|
76
|
+
})),
|
|
73
77
|
}),
|
|
74
78
|
},
|
|
75
79
|
);
|
|
@@ -114,9 +118,8 @@ const _tests = [
|
|
|
114
118
|
}),
|
|
115
119
|
];
|
|
116
120
|
|
|
117
|
-
|
|
118
|
-
/* describe(group, function () {
|
|
121
|
+
describe(group, function () {
|
|
119
122
|
tests.forEach((test) => {
|
|
120
123
|
test.run();
|
|
121
124
|
});
|
|
122
|
-
});
|
|
125
|
+
});
|
package/src/main.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BuiltinModule } from './BuiltinModule.js';
|
|
2
2
|
import { ChatBridge } from './modules/chatBridge/index.js';
|
|
3
|
+
import { DailyRewards } from './modules/dailyRewards/index.js';
|
|
3
4
|
import { EconomyUtils } from './modules/economyUtils/index.js';
|
|
4
5
|
import { GeoBlock } from './modules/geoBlock/index.js';
|
|
5
6
|
import { Gimme } from './modules/gimme/index.js';
|
|
@@ -30,6 +31,7 @@ export function getModules(): Array<BuiltinModule<unknown>> {
|
|
|
30
31
|
new Lottery(),
|
|
31
32
|
new GeoBlock(),
|
|
32
33
|
new TimedShutdown(),
|
|
34
|
+
new DailyRewards(),
|
|
33
35
|
];
|
|
34
36
|
}
|
|
35
37
|
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { takaro, data, TakaroUserError, checkPermission } from '@takaro/helpers';
|
|
2
|
+
import { DAILY_KEY, STREAK_KEY, getMultiplier } from './utils.js';
|
|
3
|
+
|
|
4
|
+
async function main() {
|
|
5
|
+
const { pog, gameServerId, module: mod } = data;
|
|
6
|
+
|
|
7
|
+
if (!checkPermission(pog, 'DAILY_CLAIM')) {
|
|
8
|
+
throw new TakaroUserError('You do not have permission to claim daily rewards.');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Get last claim time
|
|
12
|
+
const lastClaimRes = await takaro.variable.variableControllerSearch({
|
|
13
|
+
filters: {
|
|
14
|
+
key: [DAILY_KEY],
|
|
15
|
+
gameServerId: [gameServerId],
|
|
16
|
+
playerId: [pog.playerId],
|
|
17
|
+
moduleId: [mod.moduleId],
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const now = new Date();
|
|
22
|
+
let streak = 1;
|
|
23
|
+
|
|
24
|
+
if (lastClaimRes.data.data.length > 0) {
|
|
25
|
+
const lastClaim = new Date(JSON.parse(lastClaimRes.data.data[0].value));
|
|
26
|
+
const hoursSinceLastClaim = (now - lastClaim) / (1000 * 60 * 60);
|
|
27
|
+
|
|
28
|
+
// Check if 24 hours have passed
|
|
29
|
+
if (hoursSinceLastClaim < 24) {
|
|
30
|
+
const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);
|
|
31
|
+
throw new TakaroUserError(`You can claim your next reward at ${nextClaimTime.toLocaleString()}`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Get current streak
|
|
35
|
+
const streakRes = await takaro.variable.variableControllerSearch({
|
|
36
|
+
filters: {
|
|
37
|
+
key: [STREAK_KEY],
|
|
38
|
+
gameServerId: [gameServerId],
|
|
39
|
+
playerId: [pog.playerId],
|
|
40
|
+
moduleId: [mod.moduleId],
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (streakRes.data.data.length > 0) {
|
|
45
|
+
// If claimed within 48 hours, increment streak
|
|
46
|
+
if (hoursSinceLastClaim < 48) {
|
|
47
|
+
streak = Math.min(JSON.parse(streakRes.data.data[0].value) + 1, mod.userConfig.maxStreak);
|
|
48
|
+
await takaro.variable.variableControllerUpdate(streakRes.data.data[0].id, {
|
|
49
|
+
value: JSON.stringify(streak),
|
|
50
|
+
});
|
|
51
|
+
} else {
|
|
52
|
+
// Reset streak if more than 48 hours
|
|
53
|
+
await takaro.variable.variableControllerUpdate(streakRes.data.data[0].id, {
|
|
54
|
+
value: JSON.stringify(1),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
// Create new streak record
|
|
59
|
+
await takaro.variable.variableControllerCreate({
|
|
60
|
+
key: STREAK_KEY,
|
|
61
|
+
value: JSON.stringify(1),
|
|
62
|
+
gameServerId,
|
|
63
|
+
playerId: pog.playerId,
|
|
64
|
+
moduleId: mod.moduleId,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Update last claim time
|
|
69
|
+
await takaro.variable.variableControllerUpdate(lastClaimRes.data.data[0].id, {
|
|
70
|
+
value: JSON.stringify(now),
|
|
71
|
+
});
|
|
72
|
+
} else {
|
|
73
|
+
// First time claim
|
|
74
|
+
await takaro.variable.variableControllerCreate({
|
|
75
|
+
key: DAILY_KEY,
|
|
76
|
+
value: JSON.stringify(now),
|
|
77
|
+
gameServerId,
|
|
78
|
+
playerId: pog.playerId,
|
|
79
|
+
moduleId: mod.moduleId,
|
|
80
|
+
});
|
|
81
|
+
await takaro.variable.variableControllerCreate({
|
|
82
|
+
key: STREAK_KEY,
|
|
83
|
+
value: JSON.stringify(1),
|
|
84
|
+
gameServerId,
|
|
85
|
+
playerId: pog.playerId,
|
|
86
|
+
moduleId: mod.moduleId,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const multiplier = await getMultiplier(pog);
|
|
91
|
+
const baseReward = mod.userConfig.baseReward * streak * multiplier;
|
|
92
|
+
let bonusReward = 0;
|
|
93
|
+
let milestoneMessage = '';
|
|
94
|
+
|
|
95
|
+
// Check for milestones
|
|
96
|
+
for (const milestone of mod.userConfig.milestoneRewards) {
|
|
97
|
+
if (streak === milestone.days) {
|
|
98
|
+
bonusReward = milestone.reward;
|
|
99
|
+
milestoneMessage = `\n${milestone.message}`;
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Award total rewards
|
|
105
|
+
const totalReward = baseReward + bonusReward;
|
|
106
|
+
await takaro.playerOnGameserver.playerOnGameServerControllerAddCurrency(gameServerId, pog.playerId, {
|
|
107
|
+
currency: totalReward,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const currencyName = (await takaro.settings.settingsControllerGetOne('currencyName', gameServerId)).data.data.value;
|
|
111
|
+
await pog.pm(
|
|
112
|
+
`Daily reward claimed! You received ${totalReward} ${currencyName}\n` +
|
|
113
|
+
`Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x bonus!)` : ''}` +
|
|
114
|
+
milestoneMessage,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
await main();
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { data, takaro } from '@takaro/helpers';
|
|
2
|
+
import { getPlayerStreak, getLastClaim, getMultiplier } from './utils.js';
|
|
3
|
+
|
|
4
|
+
async function main() {
|
|
5
|
+
const { pog, gameServerId, module: mod } = data;
|
|
6
|
+
|
|
7
|
+
const streak = await getPlayerStreak(gameServerId, pog.playerId, mod.moduleId);
|
|
8
|
+
const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId);
|
|
9
|
+
const multiplier = await getMultiplier(pog);
|
|
10
|
+
const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;
|
|
11
|
+
|
|
12
|
+
if (!streak || !lastClaim) {
|
|
13
|
+
await pog.pm(`You haven't claimed any daily rewards yet! Use ${prefix}daily to get started.`);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);
|
|
18
|
+
const now = new Date();
|
|
19
|
+
const canClaim = now >= nextClaimTime;
|
|
20
|
+
|
|
21
|
+
// Find next milestone
|
|
22
|
+
let nextMilestone = null;
|
|
23
|
+
for (const milestone of mod.userConfig.milestoneRewards) {
|
|
24
|
+
if (milestone.days > streak) {
|
|
25
|
+
nextMilestone = milestone;
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let message = `Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x donor bonus!)` : ''}\n`;
|
|
31
|
+
message += canClaim
|
|
32
|
+
? `Your daily reward is available! Use ${prefix}daily to claim it!\n`
|
|
33
|
+
: `Next reward available at: ${nextClaimTime.toLocaleString()}\n`;
|
|
34
|
+
|
|
35
|
+
if (nextMilestone) {
|
|
36
|
+
message += `\nšÆ Next milestone: ${nextMilestone.days} days (${nextMilestone.days - streak} days to go!)`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
await pog.pm(message);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
await main();
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { takaro, data } from '@takaro/helpers';
|
|
2
|
+
import { STREAK_KEY } from './utils.js';
|
|
3
|
+
|
|
4
|
+
async function main() {
|
|
5
|
+
const { pog, gameServerId, module: mod, arguments: args } = data;
|
|
6
|
+
|
|
7
|
+
// Limit count to reasonable number
|
|
8
|
+
const count = Math.min(Math.max(1, args.count), 50);
|
|
9
|
+
|
|
10
|
+
// Get all streaks
|
|
11
|
+
const streaksRes = await takaro.variable.variableControllerSearch({
|
|
12
|
+
filters: {
|
|
13
|
+
key: [STREAK_KEY],
|
|
14
|
+
gameServerId: [gameServerId],
|
|
15
|
+
moduleId: [mod.moduleId],
|
|
16
|
+
},
|
|
17
|
+
limit: 1000, // Get all possible streaks
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
if (streaksRes.data.data.length === 0) {
|
|
21
|
+
await pog.pm('No players have started their daily streak yet!');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Sort by streak value
|
|
26
|
+
const sortedStreaks = streaksRes.data.data
|
|
27
|
+
.map((record) => ({
|
|
28
|
+
playerId: record.playerId,
|
|
29
|
+
streak: JSON.parse(record.value),
|
|
30
|
+
}))
|
|
31
|
+
.sort((a, b) => b.streak - a.streak)
|
|
32
|
+
.slice(0, count);
|
|
33
|
+
|
|
34
|
+
// Get player names
|
|
35
|
+
const playerDetails = await Promise.all(
|
|
36
|
+
sortedStreaks.map(async (record) => {
|
|
37
|
+
const player = (await takaro.player.playerControllerGetOne(record.playerId)).data.data;
|
|
38
|
+
return {
|
|
39
|
+
name: player.name,
|
|
40
|
+
streak: record.streak,
|
|
41
|
+
};
|
|
42
|
+
}),
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
// Build message
|
|
46
|
+
let message = `Top ${count} Daily Streaks:\n\n`;
|
|
47
|
+
playerDetails.forEach((player, index) => {
|
|
48
|
+
message += `${index + 1}. ${player.name}: ${player.streak} days\n`;
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
await pog.pm(message);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
await main();
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { takaro, checkPermission } from '@takaro/helpers';
|
|
2
|
+
|
|
3
|
+
export const DAILY_KEY = 'daily_timestamp';
|
|
4
|
+
export const STREAK_KEY = 'daily_streak';
|
|
5
|
+
|
|
6
|
+
export async function getMultiplier(pog) {
|
|
7
|
+
const perm = checkPermission(pog, 'DAILY_REWARD_MULTIPLIER');
|
|
8
|
+
if (perm) return perm.count;
|
|
9
|
+
return 1;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function getPlayerStreak(gameServerId, playerId, moduleId) {
|
|
13
|
+
const streakRes = await takaro.variable.variableControllerSearch({
|
|
14
|
+
filters: {
|
|
15
|
+
key: [STREAK_KEY],
|
|
16
|
+
gameServerId: [gameServerId],
|
|
17
|
+
playerId: [playerId],
|
|
18
|
+
moduleId: [moduleId],
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return streakRes.data.data.length ? parseInt(JSON.parse(streakRes.data.data[0].value)) : 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function getLastClaim(gameServerId, playerId, moduleId) {
|
|
26
|
+
const lastClaimRes = await takaro.variable.variableControllerSearch({
|
|
27
|
+
filters: {
|
|
28
|
+
key: [DAILY_KEY],
|
|
29
|
+
gameServerId: [gameServerId],
|
|
30
|
+
playerId: [playerId],
|
|
31
|
+
moduleId: [moduleId],
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return lastClaimRes.data.data.length ? new Date(JSON.parse(lastClaimRes.data.data[0].value)) : null;
|
|
36
|
+
}
|