Skip to content

Outline

Rayzr522 edited this page Aug 6, 2018 · 12 revisions

General outline

States / Phases

The game is separated into a series of States (or Phases) that control almost all aspects of the game. This consists of:

  • Registering Mechanics: A phase can have some mechanics registered to it, that it will execute
  • Registering End criteria: A phase can have End criteria registered, that control when the phases ends and the next one will be entered.

The lifecycle of a phase consists mainly of two methods:

  • setup — called when the phase is being started, i.e. it becomes active. The game is now controlled by this phase and it registers all mechanics and end criteria.
  • teardown — called when the phase is being stopped. The game is no longer controlled by this phase as another one will take control. All mechanics and end criteria are now unregistered

The match includes a convenience function that can register End criteria and Mechanics that will be registered to every phase.

Some examples include:

  • Startup: The players are being spawned, locked in place and a countdown starts
  • Running: The game is actively running
  • Deathmatch: The players are brought to a deathmatch to fight each other

Mechanics

To augment and alter the gameplay, you need to have many smaller pieces of logic. They are often quite similar between games though and can therefore profit from an abstraction. In this library they are extracted into Mechanics. An example for a mechanic could be OneShotKill for One in the chamber, a GameModeMechanic that sets the gamemode, an ArrowTrail that just traces arrows and so on.
To facilitate the introduction of Classes (RPG-style) each mechanic can optionally take a predicate that states whether a player can use it. If the player can not use the mechanic, it will just disable itself for the player. Using this a mechanic — like spells or double jump and similar things — can be constrained to specific classes, while still being added all the same to the game.

Mechanics are executed by Triggers (see below).

Triggers

Mechanics need to be triggered by something. This will typically be an event or a repeating Runnable ("Ticker"), but it could be anything. To make that possible, the trigger for a mechanic is abstracted into a Trigger. Predefined triggers for event listening as well as tickers will be provided, the rest can be freely supplied by the user. Additionally triggers can listen to Attribute changes.

You should be able to add more than one trigger to a mechanic.

End criteria

If you have States or Phases you logically need a way to switch between them. This is where End criteria come in.

End criteria have two properties: a trigger, and a phase to switch to. When the trigger activates, the match then switches to the phase with which the end criteria is associated. This allows complex phase systems such as looping phases, different modes based on number of points in a game, etc.

Data providers

As Mechanics and End criteria both need to be aware of the game state, you need something that defines what is actually saved and stored. This differs between minigames, so it follows a similar concept as the Mechanics — you just add a new DataProvider that keeps track of it. An example could be a KillTracker or anything else that fires an event or can be deduced by running periodically or the player state.

Arenas

A game needs an arena — but what exactly is part of it? Currently the arena stores a set of Attributes. These are just small pieces of data that define what the arena is: KillRegion, Bounds, MaxPlayers are all Attributes. These also have a small twist: They know what command can create them. This means that if you define an arena to have a given amount of attributes, the commands to initialize that arena will automatically be created and registered. Coupling the commands and attributes in this way allows each arena to have its own unique composition and makes it easily extensible.

Arenas have a few attributes built in:

  1. id - The unqiue ID of the arena. See Identifiers for format.
  2. name - (Optional) A custom display name for the arena. This supports Minecraft formatting characters, multiple words, and does not need to be unique.
  3. region - The main arena region.
  4. minPlayers and maxPlayers - The minimum and maximum number of players that this arena supports. This is then used by the match to determine which arenas can be used for the number of players that are currently queued.
  5. spawnLocations - A list of Spawn Points relative to the arena's origin.
  6. lobby - (Optional) The ID of the lobby template to use for this arena. If it is ommitted, then the default lobby for the minigame will be used. All hell will break loose if there is no default lobby for the minigame.
  7. lobbyOffset - The relativeoffset from the origin of the arena to the origin of the lobby. Used for placing the lobby.

Spawn Points

A spawn point is a point in an arena relative to its origin where a player is teleported at the start of a match. Not only do spawn points have a relative location, they also have an optional team attribute which sets which team the point is for. The system then teleports a player to a spawn point based on their team.

Teleporting players to spawnpoints is all handled by a premade mechanic which determines where to route each player via a Spawn Strategy in the form of (List<GamePlayer>, List<Spawn>) -> Map<GamePlayer, Spawn>. This allows for easy custom spawn strategies. Premade strategies will include FFA and TEAMS.

Lobbies

Lobbies are separate entities from their arena counterparts, and they are where the player is teleported while the match is waiting for more players to join. The lobbies have attributes, just like arenas, and the defaults are these:

  1. id - The unqiue ID of the lobby. See Identifiers for format.
  2. spawnLocation - The location (relative to the origin) where players should be teleported to upon joining.
  3. region - The region that encapsulates the lobby.

Data Attributes

Data Attributes are little tidbits of information that make up the state of a player and the match. They are at their core Observable values, meaning you can listen to them change. This is very useful to bind triggers to them (e.g. "Trigger on five kills in a row") and can be used to compose them together.

This composition allows some of the match attributes to be derived from individual players, but also allows you to express things like "If the team has 20 kills together" in a fluent and consistent way.

Player data

During a game arbitrary data should be able to be stored directly onto the player object using a thin wrapper to allow each mechanic and other components to easily store relevant state.

Additionally player data should also consist of Data Attributes.

Identifiers

An identifier is a single-word context-unique string, which is human-readable and chosen by the end user. This is used by arenas and lobbies, for example.

Scoreboards

Scoresboards are used by minigames to display information pertaining to a match. They would be managed by the match, and there would be certain properties that could be added by the match which would persist through all matches. But then, if a certain phase needed to display an extra bit of information, it could just tell the match to append that property & label.

Scoreboards take advantage of the observable nature of Data Attributes to automatically update when the values of the properties to which they are attached update.

Modes

Modes determine the gameplay for a given match, allowing different flavors of gameplay such as Normal vs. Extreme, PvP vs. PvE, etc.

  1. Provides all the phases for a match, including end criteria and mechanics.
  2. Provides global (phase-agnostic) mechanics.
  3. Mode is determined by the Match.

Methods:

  • #getPhases() - gets all the phases
  • #getGlobalMechanics() - gets all the global mechanics
  • #getId() - gets the ID/name of the mode

Teams

Teams are pretty much self-explanatory. They allow for things like 2v2 modes of games, etc. Any kind of friendly-fire or anything like that would be handled by a premade mechanic.

Teams have the following attributes by default:

  • id (String) - The ID of the team (e.g. red, blue, green, humans, zombies, etc.)
  • membersTotal (Int) - The # of players on this team
  • membersAlive (Int) - The # of currently alive players on this team