Skip to content

Commit 536ee26

Browse files
committed
Merge branch 'main' of github.com:x-team/GamesHQ-API into main
2 parents e1cdf03 + e6c467c commit 536ee26

File tree

15 files changed

+426
-96
lines changed

15 files changed

+426
-96
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import Joi from 'joi';
2+
3+
export const commandArenaRequestSchema = Joi.object({
4+
command: Joi.string().required(),
5+
}).required();
6+
7+
export const commandArenaResponseSchema = Joi.object({
8+
message: Joi.string().required(),
9+
}).required();
10+
11+
export const actionArenaRequestSchema = Joi.object({
12+
action: Joi.string().required(),
13+
value: Joi.array().items(Joi.string()),
14+
}).required();

src/games/arena/actions/index.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ const actionReply = {
4646
needToSelectZoneToDelete: `Please select a valid zone to delete`,
4747
};
4848

49-
function arenaPlayerSwitchActions(action: string, args: number | number[], userRequesting: User) {
49+
export function arenaPlayerSwitchActions(
50+
action: string,
51+
args: number | number[],
52+
userRequesting: User
53+
) {
5054
const singleArg = typeof args === 'number' ? args : args[0];
5155
const arrayArgs = typeof args === 'number' ? [args] : args;
5256
switch (action) {

src/games/arena/commands/index.ts

+1-24
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
import { logger } from '../../../config';
21
import type { User } from '../../../models';
3-
import { gameResponseToSlackHandler } from '../../../modules/slack/utils';
42
import { getGameResponse } from '../../utils';
53
import { ARENA_SLACK_COMMANDS } from '../consts';
64
import { ArenaRepository } from '../repositories/arena/arena';
75
import { ArenaEngine } from '../repositories/arena/engine';
8-
import { arenaCommandReply } from '../repositories/arena/replies';
96
import { ZoneRepository } from '../repositories/zones/zone';
10-
import { arenaNotifyEphemeral } from '../utils';
117

128
const arena = new ArenaRepository(ArenaEngine.getInstance());
139
const zone = ZoneRepository.getInstance();
@@ -75,26 +71,7 @@ export function arenaSwitchCommand({
7571
case ARENA_SLACK_COMMANDS.NARROW_WEAPONS:
7672
return arena.startNarrowWeaponsQuestion(userRequesting);
7773
case ARENA_SLACK_COMMANDS.START_ROUND:
78-
arena
79-
.startRound(userRequesting)
80-
.then(async (reply) => {
81-
const slackResponseBody = gameResponseToSlackHandler(reply);
82-
await arenaNotifyEphemeral(
83-
slackResponseBody.text ?? 'Something went wrong',
84-
userRequesting.slackId!,
85-
userRequesting.slackId!
86-
);
87-
})
88-
.catch(async (e) => {
89-
logger.error('Error in Slack Command: The Arena');
90-
logger.error(e);
91-
await arenaNotifyEphemeral(
92-
'Something went wrong',
93-
userRequesting.slackId!,
94-
userRequesting.slackId!
95-
);
96-
});
97-
return getGameResponse(arenaCommandReply.adminFinishedRound());
74+
return arena.startRound(userRequesting);
9875
// PLAYERS
9976
case ARENA_SLACK_COMMANDS.ACTIONS:
10077
return arena.actionsMenu(userRequesting);

src/games/arena/consts.ts

+18
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,24 @@ export enum ARENA_SECONDARY_ACTIONS {
103103
DELETE_ZONE = 'delete-zone',
104104
}
105105

106+
export const ARENA_DASHBOARD_COMMANDS = [
107+
ARENA_SLACK_COMMANDS.NEW_GAME.toString(),
108+
ARENA_SLACK_COMMANDS.START_ROUND.toString(),
109+
ARENA_SLACK_COMMANDS.LIST_PLAYERS.toString(),
110+
ARENA_SLACK_COMMANDS.GIVE_EVERYONE_WEAPON.toString(),
111+
ARENA_SLACK_COMMANDS.NARROW_ZONES.toString(),
112+
ARENA_SLACK_COMMANDS.NARROW_WEAPONS.toString(),
113+
ARENA_SLACK_COMMANDS.END_GAME.toString(),
114+
];
115+
116+
export const ARENA_DASHBOARD_ACTIONS = [
117+
ARENA_SECONDARY_ACTIONS.CANCEL_END_GAME.toString(),
118+
ARENA_SECONDARY_ACTIONS.CONFIRM_END_GAME.toString(),
119+
ARENA_SECONDARY_ACTIONS.CONFIRM_NARROW_ZONES.toString(),
120+
ARENA_SECONDARY_ACTIONS.CONFIRM_NARROW_WEAPONS.toString(),
121+
ARENA_SECONDARY_ACTIONS.CONFIRM_GIVE_EVERYONE_WEAPONS.toString(),
122+
];
123+
106124
export enum ARENA_HEALTHKITS {
107125
COMMON = 'arena health kit',
108126
}

src/games/arena/repositories/arena/actions/admin/create-or-finish-game.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { User } from '../../../../../../models';
22
import { findActiveArenaGame, startArenaGame } from '../../../../../../models/ArenaGame';
3+
import { endActiveRound } from '../../../../../../models/ArenaRound';
34
import { activateAllArenaZones } from '../../../../../../models/ArenaZone';
45
import { enableAllItems } from '../../../../../../models/GameItemAvailability';
56
import { GAME_TYPE } from '../../../../../consts/global';
@@ -69,6 +70,7 @@ export async function endGame(userRequesting: User) {
6970
return getGameError(arenaCommandReply.noActiveGame());
7071
}
7172
await enableAllItems(game._gameTypeId, transaction);
73+
await endActiveRound(transaction);
7274
await game.endGame(transaction);
7375
await activateAllArenaZones(transaction);
7476
await publishArenaMessage(arenaCommandReply.channelEndGame(game), true);
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { logger } from '../../../../../../config';
12
import type { User } from '../../../../../../models';
23
import { findLivingPlayersByGame } from '../../../../../../models/ArenaPlayer';
34
import {
@@ -11,81 +12,118 @@ import {
1112
findRingSystemZonesToDeactivate,
1213
ringDeactivationSystem,
1314
} from '../../../../../../models/ArenaZone';
15+
import { gameResponseToSlackHandler } from '../../../../../../modules/slack/utils';
1416
import { ONE, THREE, ZERO } from '../../../../../consts/global';
1517
import { adminAction, getGameError, getGameResponse } from '../../../../../utils';
16-
import { processWinner, publishArenaMessage, withArenaTransaction } from '../../../../utils';
18+
import {
19+
processWinner,
20+
publishArenaMessage,
21+
withArenaTransaction,
22+
arenaNotifyEphemeral,
23+
} from '../../../../utils';
1724
import { ArenaEngine } from '../../engine';
1825
import { arenaCommandReply } from '../../replies';
1926

2027
const arenaGameEngine = ArenaEngine.getInstance();
2128

2229
export async function startRoundCommand(userRequesting: User) {
23-
return withArenaTransaction(async (transaction) => {
24-
const isAdmin = adminAction(userRequesting);
25-
if (!isAdmin) {
26-
return getGameError(arenaCommandReply.adminsOnly());
27-
}
28-
const round = await findActiveRound(true, transaction);
29-
if (!round) {
30-
return getGameError(arenaCommandReply.noActiveRound());
31-
}
32-
const isEveryoneVisible = round.isEveryoneVisible;
33-
// Lock the round so no one can send more commands
34-
arenaGameEngine.setRoundState(true);
35-
await publishArenaMessage(arenaCommandReply.channelEndingTheRound(), true);
30+
void withArenaTransaction(async (transaction) => {
31+
try {
32+
const isAdmin = adminAction(userRequesting);
33+
if (!isAdmin) {
34+
return getGameError(arenaCommandReply.adminsOnly());
35+
}
36+
const round = await findActiveRound(true, transaction);
37+
if (!round) {
38+
return getGameError(arenaCommandReply.noActiveRound());
39+
}
40+
const isEveryoneVisible = round.isEveryoneVisible;
41+
// Lock the round so no one can send more commands
42+
arenaGameEngine.setRoundState(true);
43+
await publishArenaMessage(arenaCommandReply.channelEndingTheRound(), true);
3644

37-
// 0. Set IDLE players to "Stay on location" action
38-
await arenaGameEngine.assignZoneActionToIdlePlayers(round, transaction);
39-
await round.customReload(true, transaction);
40-
// 1. Actions (Per Zone)
41-
const zonesWithPlayers = await findArenaZonesWithPlayers(transaction);
42-
for (const zone of zonesWithPlayers) {
43-
await arenaGameEngine.runRound(zone, round, transaction);
44-
}
45-
// 2. Movement: Players Location
46-
await arenaGameEngine.processChangeLocation(round._actions ?? [], transaction);
45+
// 0. Set IDLE players to "Stay on location" action
46+
await arenaGameEngine.assignZoneActionToIdlePlayers(round, transaction);
47+
await round.customReload(true, transaction);
48+
// 1. Actions (Per Zone)
49+
const zonesWithPlayers = await findArenaZonesWithPlayers(transaction);
50+
for (const zone of zonesWithPlayers) {
51+
await arenaGameEngine.runRound(zone, round, transaction);
52+
}
53+
// 2. Movement: Players Location
54+
await arenaGameEngine.processChangeLocation(round._actions ?? [], transaction);
4755

48-
const playersAlive = await findLivingPlayersByGame(
49-
round._arenaGame?._gameId!,
50-
false,
51-
transaction
52-
);
53-
const amountOfPlayersAlive = playersAlive.length;
56+
const playersAlive = await findLivingPlayersByGame(
57+
round._arenaGame?._gameId!,
58+
false,
59+
transaction
60+
);
61+
const amountOfPlayersAlive = playersAlive.length;
5462

55-
await publishArenaMessage(arenaCommandReply.channelTotalPlayersAlive(amountOfPlayersAlive));
63+
await publishArenaMessage(arenaCommandReply.channelTotalPlayersAlive(amountOfPlayersAlive));
5664

57-
// Search for a winner
58-
await processWinner(round, transaction);
59-
await startRound(round._gameId, userRequesting.id, isEveryoneVisible, transaction);
60-
const roundsCompleted = await countRoundsCompleted(transaction);
65+
// Search for a winner
66+
await processWinner(round, transaction);
67+
await startRound(round._gameId, userRequesting.id, isEveryoneVisible, transaction);
68+
const roundsCompleted = await countRoundsCompleted(transaction);
6169

62-
const activeZonesForCurrentRound = await findActiveArenaZones(transaction);
70+
const activeZonesForCurrentRound = await findActiveArenaZones(transaction);
6371

64-
if (round._arenaGame?.hasZoneDeactivation && activeZonesForCurrentRound.length > ONE) {
65-
if ((roundsCompleted + ONE) % THREE === ZERO) {
66-
const zonesToDeactivate = await findRingSystemZonesToDeactivate(
67-
{
68-
ringSystemAlgorithm: round._arenaGame?.ringSystemAlgorithm,
69-
currentRingDeactivation: round._arenaGame?.currentRingDeactivation,
70-
},
71-
transaction
72-
);
73-
await publishArenaMessage(arenaCommandReply.channelZonesToDeactivate(zonesToDeactivate));
72+
if (round._arenaGame?.hasZoneDeactivation && activeZonesForCurrentRound.length > ONE) {
73+
if ((roundsCompleted + ONE) % THREE === ZERO) {
74+
const zonesToDeactivate = await findRingSystemZonesToDeactivate(
75+
{
76+
ringSystemAlgorithm: round._arenaGame?.ringSystemAlgorithm,
77+
currentRingDeactivation: round._arenaGame?.currentRingDeactivation,
78+
},
79+
transaction
80+
);
81+
await publishArenaMessage(arenaCommandReply.channelZonesToDeactivate(zonesToDeactivate));
82+
}
83+
84+
if (roundsCompleted % THREE === ZERO) {
85+
await publishArenaMessage(arenaCommandReply.channelRunningRingSystem());
86+
await ringDeactivationSystem(round._arenaGame, transaction);
87+
}
7488
}
7589

76-
if (roundsCompleted % THREE === ZERO) {
77-
await publishArenaMessage(arenaCommandReply.channelRunningRingSystem());
78-
await ringDeactivationSystem(round._arenaGame, transaction);
90+
const activeZonesForNextRound = await findActiveArenaZones(transaction);
91+
await publishArenaMessage(arenaCommandReply.channelActiveZones(activeZonesForNextRound));
92+
if (activeZonesForNextRound.length > ONE) {
93+
await publishArenaMessage(arenaCommandReply.playersMoving());
7994
}
80-
}
95+
// unlock the round so everyone can send more commands
96+
arenaGameEngine.setRoundState(false);
97+
98+
const reply = getGameResponse(arenaCommandReply.adminFinishedRound());
99+
100+
const slackResponseBody = gameResponseToSlackHandler(reply);
101+
arenaNotifyEphemeral(
102+
slackResponseBody.text ?? 'Something went wrong',
103+
userRequesting.slackId!,
104+
userRequesting.slackId!
105+
).catch((e) => {
106+
onError(e, userRequesting);
107+
});
81108

82-
const activeZonesForNextRound = await findActiveArenaZones(transaction);
83-
await publishArenaMessage(arenaCommandReply.channelActiveZones(activeZonesForNextRound));
84-
if (activeZonesForNextRound.length > ONE) {
85-
await publishArenaMessage(arenaCommandReply.playersMoving());
109+
return reply;
110+
} catch (e) {
111+
onError(e, userRequesting);
112+
return getGameError('Something went wrong');
86113
}
87-
// unlock the round so everyone can send more commands
88-
arenaGameEngine.setRoundState(false);
89-
return getGameResponse(arenaCommandReply.adminFinishedRound());
90114
});
115+
116+
return getGameResponse(arenaCommandReply.adminStartedNewRound());
91117
}
118+
119+
const onError = (error: any, userRequesting: User) => {
120+
// return
121+
logger.error('onError:', error);
122+
arenaNotifyEphemeral(
123+
'Something went wrong',
124+
userRequesting.slackId!,
125+
userRequesting.slackId!
126+
).catch((e) => {
127+
logger.error('Something went wrong', e);
128+
});
129+
};

src/games/arena/utils/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ export async function processWinner(round: ArenaRound, transaction: Transaction)
118118
false,
119119
transaction
120120
);
121+
121122
if (playersAlive.length === ONE) {
122123
const [winner] = playersAlive;
123124
await publishArenaMessage(arenaCommandReply.playerWinsGame(winner._user?.slackId!));

src/models/ArenaRound.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,6 @@ export function findActiveRound(includeAll: boolean, transaction?: Transaction)
188188
{
189189
association: Game.associations._gameType,
190190
attributes: ['id', 'name'],
191-
// where: {
192-
// name: GAME_TYPE.ARENA,
193-
// },
194191
},
195192
],
196193
},
@@ -208,10 +205,7 @@ export async function startRound(
208205
isEveryoneVisible: boolean,
209206
transaction: Transaction
210207
) {
211-
const activeRound = await findActiveRound(false, transaction);
212-
if (activeRound) {
213-
await activeRound.endRound(transaction);
214-
}
208+
await endActiveRound(transaction);
215209
return createArenaRound(
216210
{
217211
_gameId: _gameId,
@@ -224,6 +218,12 @@ export async function startRound(
224218
transaction
225219
);
226220
}
221+
export async function endActiveRound(transaction: Transaction) {
222+
const activeRound = await findActiveRound(false, transaction);
223+
if (activeRound) {
224+
await activeRound.endRound(transaction);
225+
}
226+
}
227227

228228
export async function createArenaRound(
229229
{

0 commit comments

Comments
 (0)