Skip to content

Commit cc11ec0

Browse files
committed
Support the environment settings in games
1 parent 78bdae8 commit cc11ec0

File tree

5 files changed

+105
-8
lines changed

5 files changed

+105
-8
lines changed

javascript/features/games/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ derby and racing games.
1818

1919
## Options when registering a game
2020
When registering a game with the `Games.registerGame()` function, you pass in a class that extends
21-
the [Game class](game.js) and an options dictionary.
21+
the [GameBase class](game_base.js) ([interface](game.js)) and an options dictionary.
2222

2323
### Required configuration
2424

javascript/features/games/environment_settings.js

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,43 @@
55
import { GameCustomSetting } from 'features/games/game_custom_setting.js';
66
import { Menu } from 'components/menu/menu.js';
77

8+
// Configuration and mappings for the gravity options available to games.
9+
const kGravityConfiguration = new Map([
10+
[ 'Low', 0.005 ],
11+
[ 'Normal', null ],
12+
[ 'High', 0.011 ],
13+
]);
14+
15+
// Configuration and mappings for the time options available to games.
16+
const kTimeConfiguration = new Map([
17+
[ 'Morning', 8 ],
18+
[ 'Afternoon', 15 ],
19+
[ 'Evening', 20 ],
20+
[ 'Night', 2 ],
21+
]);
22+
23+
// Configuration and mappings for the weather options available to games.
24+
const kWeatherConfiguration = new Map([
25+
[ 'Cloudy', 7 ],
26+
[ 'Foggy', 9 ],
27+
[ 'Heatwave', 11 ],
28+
[ 'Rainy', 8 ],
29+
[ 'Sandstorm', 19 ],
30+
[ 'Sunny', 10 ],
31+
]);
32+
833
// Represents the environment for minigames, which can be customised to the player's liking. This
934
// includes the time, the weather, as well as the gravity level to apply.
1035
export class EnvironmentSettings extends GameCustomSetting {
1136
// Options available for each of the configuration values.
12-
static kTimeOptions = [ 'Morning', 'Afternoon', 'Evening', 'Night' ];
13-
static kWeatherOptions = [ 'Cloudy', 'Foggy', 'Heatwave', 'Rainy', 'Sandstorm', 'Sunny' ];
14-
static kGravityOptions = [ 'Low', 'Normal', 'High' ];
37+
static kGravityOptions = [ ...kGravityConfiguration.keys() ];
38+
static kTimeOptions = [ ...kTimeConfiguration.keys() ];
39+
static kWeatherOptions = [ ...kWeatherConfiguration.keys() ];
40+
41+
// Returns the actual in-game values for the given |option|.
42+
static getGravityForOption(option) { return kGravityConfiguration.get(option) ?? null; }
43+
static getTimeForOption(option) { return kTimeConfiguration.get(option) ?? null; }
44+
static getWeatherForOption(option) { return kWeatherConfiguration.get(option) ?? null; }
1545

1646
// Returns the value that is to be displayed in the generic customization dialog for games.
1747
getCustomizationDialogValue(currentValue) {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2020 Las Venturas Playground. All rights reserved.
2+
// Use of this source code is governed by the MIT license, a copy of which can
3+
// be found in the LICENSE file.
4+
5+
import { EnvironmentSettings } from 'features/games/environment_settings.js';
6+
import { Game } from 'features/games/game.js';
7+
8+
// Implementation of the Game class that provides the low-level functionality offered directly by
9+
// the Games API. Most features will want to extend this class rather than Game directly.
10+
export class GameBase extends Game {
11+
#gravity_ = null;
12+
#time_ = null;
13+
#weather_ = null;
14+
15+
async onInitialized(settings, userData) {
16+
const environment = settings.get('game/environment');
17+
if (environment) {
18+
this.#gravity_ = EnvironmentSettings.getGravityForOption(environment.gravity);
19+
this.#time_ = EnvironmentSettings.getTimeForOption(environment.time);
20+
this.#weather_ = EnvironmentSettings.getWeatherForOption(environment.weather);
21+
}
22+
}
23+
24+
async onPlayerAdded(player) {
25+
// Update the gravity, time and weather for the |player|, but only when necessary.
26+
if (this.#gravity_)
27+
player.gravity = this.#gravity_;
28+
29+
if (this.#time_)
30+
player.time = [ this.#time_, 20 ];
31+
32+
if (this.#weather_)
33+
player.weather = this.#weather_;
34+
}
35+
36+
async onPlayerRemoved(player) {
37+
// Restore the gravity for the player. The |player|'s weather and time will be reset when
38+
// their state gets deserialized immediately after this.
39+
if (this.#gravity_)
40+
player.gravity = Player.kDefaultGravity;
41+
}
42+
}

javascript/features/games/game_runtime.test.js

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// Use of this source code is governed by the MIT license, a copy of which can
33
// be found in the LICENSE file.
44

5+
import { EnvironmentSettings } from 'features/games/environment_settings.js';
56
import { GameActivity } from 'features/games/game_activity.js';
7+
import { GameBase } from 'features/games/game_base.js';
68
import { GameDescription, kDefaultTickIntervalMs } from 'features/games/game_description.js';
79
import { GameRuntime } from 'features/games/game_runtime.js';
810
import { Game } from 'features/games/game.js';
@@ -247,14 +249,22 @@ describe('GameRuntime', (it, beforeEach) => {
247249
minimumPlayers: 2,
248250
maximumPlayers: 4,
249251
price: 250,
252+
253+
environment: {
254+
gravity: 'Low',
255+
time: 'Afternoon',
256+
weather: 'Foggy',
257+
},
250258
};
251259

252260
let vehicles = [ null, null ];
253-
feature.registerGame(class extends Game {
261+
feature.registerGame(class extends GameBase {
254262
nextPlayerIndex_ = 0;
255263
playerIndex_ = new Map();
256264

257-
async onInitialized(settings) {
265+
async onInitialized(settings, userData) {
266+
await super.onInitialized(settings, userData);
267+
258268
vehicles[0] = this.scopedEntities.createVehicle({
259269
modelId: 432, // tank
260270
position: new Vector(0, 0, 0),
@@ -267,14 +277,20 @@ describe('GameRuntime', (it, beforeEach) => {
267277
}
268278

269279
async onPlayerAdded(player) {
280+
await super.onPlayerAdded(player);
281+
270282
this.playerIndex_.set(player, this.nextPlayerIndex_++);
271283
}
272284

273285
async onPlayerSpawned(player) {
286+
await super.onPlayerSpawned(player);
287+
274288
player.enterVehicle(vehicles[this.playerIndex_.get(player)]);
275289
}
276290

277291
async onPlayerDeath(player, killer, reason) {
292+
await super.onPlayerDeath(player, killer, reason);
293+
278294
await this.playerLost(player);
279295
await this.playerWon(killer, 25);
280296
}
@@ -298,6 +314,9 @@ describe('GameRuntime', (it, beforeEach) => {
298314
assert.equal(
299315
manager.getPlayerActivity(russell).getActivityState(), GameActivity.kStateRegistered);
300316

317+
assert.deepEqual(gunther.time, [ 0, 0 ]);
318+
assert.equal(gunther.gravity, Player.kDefaultGravity);
319+
301320
await server.clock.advance(settings.getValue('games/registration_expiration_sec') * 1000);
302321
await runGameLoop();
303322

@@ -314,6 +333,9 @@ describe('GameRuntime', (it, beforeEach) => {
314333
assert.equal(
315334
manager.getPlayerActivity(russell).getActivityState(), GameActivity.kStateEngaged);
316335

336+
assert.deepEqual(gunther.time, [ EnvironmentSettings.getTimeForOption('Afternoon'), 20 ]);
337+
assert.equal(gunther.gravity, EnvironmentSettings.getGravityForOption('Low'));
338+
317339
assert.equal(runtime.state, GameRuntime.kStateRunning);
318340

319341
assert.isNotNull(vehicles[0]);
@@ -355,6 +377,9 @@ describe('GameRuntime', (it, beforeEach) => {
355377
// Make sure that the money has been divided as expected.
356378
assert.equal(finance.getPlayerCash(gunther), 150);
357379
assert.equal(finance.getPlayerCash(russell), 1250);
380+
381+
// Make sure that gravity was reset.
382+
assert.equal(gunther.gravity, Player.kDefaultGravity);
358383
});
359384

360385
it('is able to proportionally calculate the prize money', assert => {

javascript/features/games_deathmatch/deathmatch_game.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44

55
import { Color } from 'base/color.js';
66
import { DeathmatchPlayerState } from 'features/games_deathmatch/deathmatch_player_state.js';
7-
import { Game } from 'features/games/game.js';
7+
import { GameBase } from 'features/games/game_base.js';
88

99
// Colours that will be assigned to participants of certain teams.
1010
const kTeamColorAlpha = Color.fromHex('D84315AA'); // red
1111
const kTeamColorBravo = Color.fromHex('0277BDAA'); // blue
1212

1313
// Implementation of the `Game` interface which extends it with deathmatch-related functionality. It
1414
// exposes methods that should be called before game-specific behaviour, i.e. through super calls.
15-
export class DeathmatchGame extends Game {
15+
export class DeathmatchGame extends GameBase {
1616
// Values for map marker visibility for the participants.
1717
static kMapMarkersEnabled = 'Enabled';
1818
static kMapMarkersEnabledTeam = 'Team only';

0 commit comments

Comments
 (0)