-
Notifications
You must be signed in to change notification settings - Fork 0
Game Control
Game state is the part of the game timeline, with specific duration expressed in time units. It is represented by GameState
object. Game states are used to split the game into smaller parts to make game more controllable.
Every game state has several properties specified by arguments while invoking a constructor:
-
name
- name of the state, mainly for display -
duration
- this is the number of periods the state lasts;-1
for infinite -
period
- length of each period expressed in milliseconds;1
if not specified -
reverseTimer
- deterimnes if the game state timer shall count up from 0 or count down to 0
State declared infinite will last until the shouldEnd()
method returns true.
Lets declare an example state called WAITING_FOR_PLAYERS
:
public static final GameState WAITING_FOR_PLAYERS = new GameState("waiting", -1, 1, false) {
@Override
public void onInit() {
}
@Override
public void tick() {
}
@Override
public void onEnd() {
}
}
Note: This object is declared as final field of an anonymous subclass of
GameState
. It is recommended to do so, in case there is a need for special functionality.
As can be seen, declaration above contains empty overrides of some methods provided by GameState
class, although they aren't abstract thus their declaration is optional. Those are predefined handler methods that are called on specific action:
-
onInit()
is called when the state is initialized -
tick()
is called every time the time counter increases -
onEnd()
is called when the state is terminated -
shouldEnd()
is called whentick()
method and determines if the state should be terminated; returns false by default
GameStateTimer class is one of the key class for creating a game engine. It is a special timer that operates on GameState objects and gives ability to split the one game timeline into separate parts (game states) that differ from each other by the name, duration and happening events. That allows the user to precisely define what and when should happen in the game and control the timeline.
The timer has two counting types, which are chosen accordingly to the current state:
- normal counting - the timer counts from
0
to current state duration - counting back - the timer counts back from current state duration back to
0
Game state timer can be created using its constructor. Its object can also be fetched from the GameManager
object using getGameStateTimer()
method.
GameStateTimer gsTimer;
// Object creation
gsTimer = new GameStateTimer(this);
// Fetch from GameManager object
gsTimer = gameManager.getGameStateTimer();
Note: Despite no restriction of having multiple game state timers, it is recommended to have only one declared per game - for consistency and to avoid ambiguity.
Major purpose of GameStateTimer
is to count and switch between particular game states with no need to declare any additional statements and care for multithreading. This can be done whether manually or automatically using GstSchedule
object.
Manual control happens by using dedicated methods:
-
initialize()
- initializes specifiedGameState
object -
terminate()
- terminates the current game state and runs next from schedule if specified -
pause()
- pauses the timer if running -
resume()
- resumes the timer if paused -
prompt()
- if running, instantly executes common timer cycle iteration: checks for ending the state and callstick()
method for current state but does not count up a time
Note: If timer runs no state (ex. if it was terminated) it stores the
GameState.EMPTY
state which simply does nothing and can be only interfeared by initializing new state.
As mentioned before, timer can be applied a schedule, which determines exact order of game states that are about to be started. Intervals between the states can be replaced with objects of Await
class which is the state with no functionality but particular duration expressed in milliseconds.
Using schedules:
// Declaring schedule
GstSchedule schedule = gsTimer.getSchedule();
// Adding schedule items
schedule.addState(MY_STATE);
schedule.addState(new Await(2000));
schedule.addState(MY_OTHER_STATE);
// Declaring new GameStateTimer with associated schedule
GameStateTimer timer = new GameStateTimer(schedule, this);
ConditionalListener
adds a condition gate for the listener. The event will only be passed down to the handled listener if the condition is met. Both condition and listener are passed down to constructor in arguments. Declaration doesn't register the listener - this has to be done by calling register()
method.
Declaring custom listener with static condition method:
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerPickupItemEvent;
public class PlayerPickupItemListener implements Listener {
@EventHandler
public void onPlayerPickupItem(PlayerPickupItemEvent event) {
System.out.println(event.getPlayer().getDisplayName() + " picked up a stack of items");
}
public static boolean condition(Event event) {
if(event instanceof PlayerPickupItemEvent) {
return ((PlayerPickupItemEvent) event).getItem().getItemStack().getAmount() == 64;
}
return false;
}
}
Creating associated ConditionalListener
object:
ConditionalListener conditionalListener = new ConditionalListener(new PlayerPickupItemListener(), PlayerPickupItemListener::condition);
conditionalListener.register(this); // PlayerPickupItemListener listener registration using this plugin
If the ConditionalListener
object reference is unnecessary, the code above can be shortened to one line:
new ConditionalListener(new PlayerPickupItemListener(), PlayerPickupItemListener::condition).register();
© 2023 Kamil Więczaszek under Apache 2.0
- Java version: 8
- Build: Maven
- Minecraft version: 1.8.8+
- License: Apache 2.0