summaryrefslogtreewikicommitdiff
path: root/src/main/java/net/tylermurphy/hideAndSeek/game/Game.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/net/tylermurphy/hideAndSeek/game/Game.java')
-rw-r--r--src/main/java/net/tylermurphy/hideAndSeek/game/Game.java484
1 files changed, 367 insertions, 117 deletions
diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/Game.java b/src/main/java/net/tylermurphy/hideAndSeek/game/Game.java
index 5af8063..d04d32a 100644
--- a/src/main/java/net/tylermurphy/hideAndSeek/game/Game.java
+++ b/src/main/java/net/tylermurphy/hideAndSeek/game/Game.java
@@ -3,58 +3,64 @@ package net.tylermurphy.hideAndSeek.game;
import static net.tylermurphy.hideAndSeek.configuration.Config.*;
import net.md_5.bungee.api.ChatColor;
-import net.tylermurphy.hideAndSeek.events.Glow;
-import net.tylermurphy.hideAndSeek.events.Taunt;
-import net.tylermurphy.hideAndSeek.events.Worldborder;
-import org.bukkit.Bukkit;
-import org.bukkit.GameMode;
-import org.bukkit.Location;
-import org.bukkit.Sound;
+import net.tylermurphy.hideAndSeek.configuration.Items;
+import net.tylermurphy.hideAndSeek.database.Database;
+import net.tylermurphy.hideAndSeek.util.Status;
+import net.tylermurphy.hideAndSeek.util.WinType;
+import net.tylermurphy.hideAndSeek.world.WorldLoader;
+import org.bukkit.*;
import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Firework;
import org.bukkit.entity.Player;
import net.tylermurphy.hideAndSeek.Main;
import net.tylermurphy.hideAndSeek.util.Packet;
-import net.tylermurphy.hideAndSeek.util.Util;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.FireworkMeta;
+import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.UUID;
+import java.io.File;
+import java.util.*;
import java.util.stream.Collectors;
import static net.tylermurphy.hideAndSeek.configuration.Localization.*;
-import static net.tylermurphy.hideAndSeek.configuration.Config.*;
+import static net.tylermurphy.hideAndSeek.game.Game.broadcastMessage;
public class Game {
- public Taunt taunt;
- public Glow glow;
- public Worldborder worldborder;
+ public static Taunt taunt;
+ public static Glow glow;
+ public static WorldBorder worldBorder;
+ public static WorldLoader worldLoader;
+ public static int tick = 0;
+ public static int countdownTime = -1;
+ public static int gameId = 0;
+ public static int timeLeft = 0;
+ public static Status status = Status.STANDBY;
- private int tick = 0;
- public int countdownTime = -1;
- public int gameId = 0;
- public int timeLeft = 0;
+ static {
+ worldLoader = new WorldLoader(spawnWorld);
+ }
- public void start(Player seeker){
- if(Main.plugin.status == Status.STARTING || Main.plugin.status == Status.PLAYING) return;
- if(Bukkit.getServer().getWorld("hideandseek_"+spawnWorld) != null) {
- Main.plugin.worldLoader.rollback();
+ public static void start(Player seeker){
+ if(status == Status.STARTING || status == Status.PLAYING) return;
+ if(worldLoader.getWorld() != null) {
+ worldLoader.rollback();
} else {
- Main.plugin.worldLoader.loadMap();
+ worldLoader.loadMap();
}
- Main.plugin.board.reload();
- for(Player temp : Main.plugin.board.getPlayers()) {
+ Board.reload();
+ for(Player temp : Board.getPlayers()) {
if(temp.getName().equals(seeker.getName()))
continue;
- Main.plugin.board.addHider(temp);
+ Board.addHider(temp);
}
- Main.plugin.board.addSeeker(seeker);
+ Board.addSeeker(seeker);
currentWorldborderSize = worldborderSize;
- for(Player player : Main.plugin.board.getPlayers()) {
+ for(Player player : Board.getPlayers()) {
player.getInventory().clear();
player.setGameMode(GameMode.ADVENTURE);
player.teleport(new Location(Bukkit.getWorld("hideandseek_"+spawnWorld), spawnPosition.getX(),spawnPosition.getY(),spawnPosition.getZ()));
@@ -62,141 +68,178 @@ public class Game {
player.removePotionEffect(effect.getType());
}
}
- for(Player player : Main.plugin.board.getSeekers()) {
+ for(Player player : Board.getSeekers()) {
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS,1000000,127,false,false));
player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW,1000000,127,false,false));
player.sendTitle(ChatColor.RED + "" + ChatColor.BOLD + "SEEKER", ChatColor.WHITE + message("SEEKERS_SUBTITLE").toString(), 10, 70, 20);
}
- for(Player player : Main.plugin.board.getHiders()) {
+ for(Player player : Board.getHiders()) {
player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED,1000000,5,false,false));
player.sendTitle(ChatColor.GOLD + "" + ChatColor.BOLD + "HIDER", ChatColor.WHITE + message("HIDERS_SUBTITLE").toString(), 10, 70, 20);
}
- Worldborder.resetWorldborder("hideandseek_"+spawnWorld);
- for(Player player : Main.plugin.board.getPlayers()){
- Main.plugin.board.createGameBoard(player);
- }
- Main.plugin.board.reloadGameBoards();
- Main.plugin.status = Status.STARTING;
- int temp = Main.plugin.game.gameId;
- Util.broadcastMessage(messagePrefix + message("START_COUNTDOWN").addAmount(30));
- Util.sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(20), Main.plugin.game.gameId, 20 * 10);
- Util.sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(10), Main.plugin.game.gameId, 20 * 20);
- Util.sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(5), Main.plugin.game.gameId, 20 * 25);
- Util.sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(3), Main.plugin.game.gameId, 20 * 27);
- Util.sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(2), Main.plugin.game.gameId, 20 * 28);
- Util.sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(1), Main.plugin.game.gameId, 20 * 29);
- if(gameLength > 0) {
- timeLeft = gameLength;
+ worldBorder.resetWorldborder("hideandseek_"+spawnWorld);
+ for(Player player : Board.getPlayers()){
+ Board.createGameBoard(player);
}
+ Board.reloadGameBoards();
+ status = Status.STARTING;
+ int temp = gameId;
+ broadcastMessage(messagePrefix + message("START_COUNTDOWN").addAmount(30));
+ sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(20), gameId, 20 * 10);
+ sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(10), gameId, 20 * 20);
+ sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(5), gameId, 20 * 25);
+ sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(3), gameId, 20 * 27);
+ sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(2), gameId, 20 * 28);
+ sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(1), gameId, 20 * 29);
Bukkit.getServer().getScheduler().runTaskLater(Main.plugin, () -> {
- if(temp != Main.plugin.game.gameId) return;
- Util.broadcastMessage(messagePrefix + message("START"));
-
- for(Player player : Main.plugin.board.getPlayers()) {
- Util.resetPlayer(player);
- }
-
- if(worldborderEnabled) {
- worldborder = new Worldborder(Main.plugin.game.gameId);
- worldborder.schedule();
- }
-
- if(tauntEnabled) {
- taunt = new Taunt(Main.plugin.game.gameId);
- taunt.schedule();
- }
-
- if (glowEnabled) {
- glow = new Glow(Main.plugin.game.gameId);
- }
-
- Main.plugin.status = Status.PLAYING;
+ if(temp != gameId) return;
+ if(gameLength > 0) timeLeft = gameLength;
+ broadcastMessage(messagePrefix + message("START"));
+ for(Player player : Board.getPlayers()) resetPlayer(player);
+ if(worldborderEnabled) worldBorder = new WorldBorder();
+ if(tauntEnabled) taunt = new Taunt();
+ if (glowEnabled) glow = new Glow();
+ status = Status.PLAYING;
}, 20 * 30);
}
- public void stop(WinType type){
- if(Main.plugin.status == Status.STANDBY) return;
+ public static void stop(WinType type){
+ if(status == Status.STANDBY) return;
tick = 0;
countdownTime = -1;
- Main.plugin.status = Status.STANDBY;
- Main.plugin.game.gameId++;
+ status = Status.STANDBY;
+ gameId++;
timeLeft = 0;
- List<UUID> players = Main.plugin.board.getPlayers().stream().map(Entity::getUniqueId).collect(Collectors.toList());
+ List<UUID> players = Board.getPlayers().stream().map(Entity::getUniqueId).collect(Collectors.toList());
if(type == WinType.HIDER_WIN){
- List<UUID> winners = Main.plugin.board.getHiders().stream().map(Entity::getUniqueId).collect(Collectors.toList());
- Main.plugin.database.playerInfo.addWins(players, winners, type);
+ List<UUID> winners = Board.getHiders().stream().map(Entity::getUniqueId).collect(Collectors.toList());
+ Database.playerInfo.addWins(players, winners, type);
} else if(type == WinType.SEEKER_WIN){
List<UUID> winners = new ArrayList<>();
- winners.add(Main.plugin.board.getFirstSeeker().getUniqueId());
- Main.plugin.database.playerInfo.addWins(players, winners, type);
+ winners.add(Board.getFirstSeeker().getUniqueId());
+ Database.playerInfo.addWins(players, winners, type);
}
- Worldborder.resetWorldborder("hideandseek_"+spawnWorld);
- for(Player player : Main.plugin.board.getPlayers()) {
- Main.plugin.board.createLobbyBoard(player);
+ worldBorder.resetWorldborder("hideandseek_"+spawnWorld);
+ for(Player player : Board.getPlayers()) {
+ Board.createLobbyBoard(player);
player.setGameMode(GameMode.ADVENTURE);
- Main.plugin.board.addHider(player);
+ Board.addHider(player);
player.getInventory().clear();
player.teleport(new Location(Bukkit.getWorld(lobbyWorld), lobbyPosition.getX(),lobbyPosition.getY(),lobbyPosition.getZ()));
for(PotionEffect effect : player.getActivePotionEffects()){
player.removePotionEffect(effect.getType());
}
player.addPotionEffect(new PotionEffect(PotionEffectType.HEAL, 1, 100));
- for(Player temp : Main.plugin.board.getPlayers()) {
+ for(Player temp : Board.getPlayers()) {
Packet.setGlow(player, temp, false);
}
}
- Main.plugin.worldLoader.unloadMap();
- Main.plugin.board.reloadLobbyBoards();
+ worldLoader.unloadMap();
+ Board.reloadLobbyBoards();
+ }
+
+ public static boolean isNotSetup() {
+ if(spawnPosition.getBlockX() == 0 && spawnPosition.getBlockY() == 0 && spawnPosition.getBlockZ() == 0) return true;
+ if(lobbyPosition.getBlockX() == 0 && lobbyPosition.getBlockY() == 0 && lobbyPosition.getBlockZ() == 0) return true;
+ if(exitPosition.getBlockX() == 0 && exitPosition.getBlockY() == 0 && exitPosition.getBlockZ() == 0) return true;
+ File destenation = new File(Main.root+File.separator+"hideandseek_"+spawnWorld);
+ if(!destenation.exists()) return true;
+ return saveMinX == 0 || saveMinZ == 0 || saveMaxX == 0 || saveMaxZ == 0;
}
- public void onTick() {
+ public static void onTick() {
+ if(isNotSetup()) return;
+ if(status == Status.STANDBY) whileWaiting();
+ else if(status == Status.STARTING) whileStarting();
+ else if(status == Status.PLAYING) whilePlaying();
+ tick++;
+ }
- if(!Util.isSetup()) return;
+ public static void resetWorldborder(String worldName){
+ worldBorder.resetWorldborder(worldName);
+ }
- if(Main.plugin.status == Status.STANDBY) whileWaiting();
- else if(Main.plugin.status == Status.PLAYING) whilePlaying();
-
- if(( Main.plugin.status == Status.STARTING || Main.plugin.status == Status.PLAYING ) && Main.plugin.board.sizeHider() < 1) {
- if(announceMessagesToNonPlayers) Bukkit.broadcastMessage(gameoverPrefix + message("GAME_GAMEOVER_HIDERS_FOUND"));
- else Util.broadcastMessage(gameoverPrefix + message("GAME_GAMEOVER_HIDERS_FOUND"));
- stop(WinType.SEEKER_WIN);
- }
- if(( Main.plugin.status == Status.STARTING || Main.plugin.status == Status.PLAYING ) && Main.plugin.board.sizeSeeker() < 1) {
- if(announceMessagesToNonPlayers) Bukkit.broadcastMessage(abortPrefix + message("GAME_GAMEOVER_SEEKERS_QUIT"));
- else Util.broadcastMessage(abortPrefix + message("GAME_GAMEOVER_SEEKERS_QUIT"));
- stop(WinType.NONE);
+ public static void broadcastMessage(String message) {
+ for(Player player : Board.getPlayers()) {
+ player.sendMessage(message);
}
+ }
- tick++;
+ public static void resetPlayer(Player player) {
+ player.getInventory().clear();
+ for (PotionEffect effect : player.getActivePotionEffects()) {
+ player.removePotionEffect(effect.getType());
+ }
+ if (Board.isSeeker(player)) {
+ if(pvpEnabled)
+ for(ItemStack item : Items.SEEKER_ITEMS)
+ player.getInventory().addItem(item);
+ for(PotionEffect effect : Items.SEEKER_EFFECTS)
+ player.addPotionEffect(effect);
+ } else if (Board.isHider(player)) {
+ if(pvpEnabled)
+ for(ItemStack item : Items.HIDER_ITEMS)
+ player.getInventory().addItem(item);
+ for(PotionEffect effect : Items.HIDER_EFFECTS)
+ player.addPotionEffect(effect);
+ if(glowEnabled) {
+ ItemStack snowball = new ItemStack(Material.SNOWBALL, 1);
+ ItemMeta snowballMeta = snowball.getItemMeta();
+ assert snowballMeta != null;
+ snowballMeta.setDisplayName("Glow Powerup");
+ List<String> snowballLore = new ArrayList<>();
+ snowballLore.add("Throw to make all seekers glow");
+ snowballLore.add("Last 30s, all hiders can see it");
+ snowballLore.add("Time stacks on multi use");
+ snowballMeta.setLore(snowballLore);
+ snowball.setItemMeta(snowballMeta);
+ player.getInventory().addItem(snowball);
+ }
+ }
+ }
+ public static void removeItems(Player player){
+ for(ItemStack si : Items.SEEKER_ITEMS)
+ for(ItemStack i : player.getInventory().getContents())
+ if(si.isSimilar(i)) player.getInventory().remove(i);
+ for(ItemStack hi : Items.HIDER_ITEMS)
+ for(ItemStack i : player.getInventory().getContents())
+ if(hi.isSimilar(i)) player.getInventory().remove(i);
}
- private void whileWaiting() {
+ private static void whileWaiting() {
if(lobbyCountdownEnabled){
- if(lobbyMin <= Main.plugin.board.size()){
+ if(lobbyMin <= Board.size()){
if(countdownTime == -1)
countdownTime = countdown;
- if(Main.plugin.board.size() >= changeCountdown)
+ if(Board.size() >= changeCountdown)
countdownTime = Math.min(countdownTime, 10);
if(tick % 20 == 0)
countdownTime--;
if(countdownTime == 0){
- String seekerName = Main.plugin.board.getPlayers().stream().skip(new Random().nextInt(Main.plugin.board.size())).findFirst().get().getName();
- Player seeker = Main.plugin.board.getPlayer(seekerName);
+ Optional<Player> rand = Board.getPlayers().stream().skip(new Random().nextInt(Board.size())).findFirst();
+ if(!rand.isPresent()){
+ Main.plugin.getLogger().warning("Failed to select random seeker.");
+ return;
+ }
+ String seekerName = rand.get().getName();
+ Player seeker = Board.getPlayer(seekerName);
start(seeker);
}
} else {
countdownTime = -1;
}
}
+ }
+ private static void whileStarting(){
+ checkWinConditions();
}
- private void whilePlaying() {
-
- for(Player hider : Main.plugin.board.getHiders()) {
+ private static void whilePlaying() {
+ for(Player hider : Board.getHiders()) {
int distance = 100, temp = 100;
- for(Player seeker : Main.plugin.board.getSeekers()) {
+ for(Player seeker : Board.getSeekers()) {
try {
temp = (int) hider.getLocation().distance(seeker.getLocation());
} catch (Exception e){
@@ -222,19 +265,226 @@ public class Game {
if(distance < 20) Packet.playSound(hider, Sound.BLOCK_NOTE_BLOCK_BIT, .3f, 1f);
break;
}
-
}
-
if(tick%20 == 0) {
if(gameLength > 0) {
- Main.plugin.board.reloadGameBoards();
+ Board.reloadGameBoards();
timeLeft--;
- if(timeLeft < 1) {
- if(announceMessagesToNonPlayers) Bukkit.broadcastMessage(gameoverPrefix + message("GAME_GAMEOVER_TIME"));
- else Util.broadcastMessage(gameoverPrefix + message("GAME_GAMEOVER_TIME"));
- stop(WinType.HIDER_WIN);
+ }
+ if(worldborderEnabled) worldBorder.update();
+ if(tauntEnabled) taunt.update();
+ if (glowEnabled) glow.update();
+ }
+ checkWinConditions();
+ }
+
+ private static void checkWinConditions(){
+ if(Board.sizeHider() < 1) {
+ if(announceMessagesToNonPlayers) Bukkit.broadcastMessage(gameoverPrefix + message("GAME_GAMEOVER_HIDERS_FOUND"));
+ else broadcastMessage(gameoverPrefix + message("GAME_GAMEOVER_HIDERS_FOUND"));
+ stop(WinType.SEEKER_WIN);
+ } else if(Board.sizeSeeker() < 1) {
+ if(announceMessagesToNonPlayers) Bukkit.broadcastMessage(abortPrefix + message("GAME_GAMEOVER_SEEKERS_QUIT"));
+ else broadcastMessage(abortPrefix + message("GAME_GAMEOVER_SEEKERS_QUIT"));
+ stop(WinType.NONE);
+ } else if(timeLeft < 1) {
+ if(announceMessagesToNonPlayers) Bukkit.broadcastMessage(gameoverPrefix + message("GAME_GAMEOVER_TIME"));
+ else broadcastMessage(gameoverPrefix + message("GAME_GAMEOVER_TIME"));
+ stop(WinType.HIDER_WIN);
+ }
+ }
+
+ private static void sendDelayedMessage(String message, int gameId, int delay) {
+ Bukkit.getScheduler().runTaskLaterAsynchronously(Main.plugin, () -> {
+ if(gameId == Game.gameId)
+ broadcastMessage(message);
+ }, delay);
+ }
+
+}
+
+class Glow {
+
+ private int glowTime;
+ private boolean running;
+
+ public Glow() {
+ this.glowTime = 0;
+ }
+
+ public void onProjectile() {
+ if(glowStackable) glowTime += glowLength;
+ else glowTime = glowLength;
+ if(!running)
+ startGlow();
+ }
+
+ private void startGlow() {
+ running = true;
+ for(Player hider : Board.getHiders()) {
+ for(Player seeker : Board.getSeekers()) {
+ Packet.setGlow(hider, seeker, true);
+ }
+ }
+ }
+
+ protected void update() {
+ if(running) {
+ glowTime--;
+ glowTime = Math.max(glowTime, 0);
+ if (glowTime == 0) {
+ stopGlow();
+ }
+ }
+ }
+
+ private void stopGlow() {
+ running = false;
+ for(Player hider : Board.getHiders()) {
+ for (Player seeker : Board.getSeekers()) {
+ Packet.setGlow(hider, seeker, false);
+ }
+ }
+ }
+
+ public boolean isRunning() {
+ return running;
+ }
+
+}
+
+class Taunt {
+
+ private String tauntPlayer;
+ private int delay;
+ private boolean running;
+
+ public Taunt() {
+ this.delay = tauntDelay;
+ }
+
+ protected void update() {
+ if(delay == 0) {
+ if(running) launchTaunt();
+ else if(tauntLast || Board.size() > 1) executeTaunt();
+ } else {
+ delay--;
+ delay = Math.max(delay, 0);
+ }
+ }
+
+ private void executeTaunt() {
+ Player taunted = null;
+ int rand = (int) (Math.random()*Board.sizeHider());
+ for(Player player : Board.getPlayers()) {
+ if(Board.isHider(player)) {
+ rand--;
+ if(rand==0) {
+ taunted = player;
+ break;
}
}
}
+ if(taunted != null) {
+ taunted.sendMessage(message("TAUNTED").toString());
+ broadcastMessage(tauntPrefix + message("TAUNT"));
+ tauntPlayer = taunted.getName();
+ running = true;
+ delay = 30;
+ } else {
+ this.delay = tauntDelay;
+ }
+ }
+
+ private void launchTaunt(){
+ Player taunted1 = Board.getPlayer(tauntPlayer);
+ if(taunted1 != null) {
+ World world = taunted1.getLocation().getWorld();
+ assert world != null;
+ Firework fw = (Firework) world.spawnEntity(taunted1.getLocation(), EntityType.FIREWORK);
+ FireworkMeta fwm = fw.getFireworkMeta();
+ fwm.setPower(4);
+ fwm.addEffect(FireworkEffect.builder()
+ .withColor(Color.BLUE)
+ .withColor(Color.RED)
+ .withColor(Color.YELLOW)
+ .with(FireworkEffect.Type.STAR)
+ .with(FireworkEffect.Type.BALL)
+ .with(FireworkEffect.Type.BALL_LARGE)
+ .flicker(true)
+ .withTrail()
+ .build());
+ fw.setFireworkMeta(fwm);
+ broadcastMessage(tauntPrefix + message("TAUNT_ACTIVATE"));
+ }
+ tauntPlayer = "";
+ running = false;
+ delay = tauntDelay;
+ }
+
+ public int getDelay(){
+ return delay;
+ }
+
+ public boolean isRunning() {
+ return running;
+ }
+
+}
+
+class WorldBorder {
+
+ private int delay;
+ private boolean running;
+
+ public WorldBorder() {
+ delay = 60 * worldborderDelay;
+ }
+
+ void update(){
+ if(delay == 0){
+ if(running){
+ delay = 60 * worldborderDelay;
+ running = false;
+ }
+ else decreaceWorldborder();
+ }
+ delay--;
+ }
+
+ private void decreaceWorldborder() {
+ if(currentWorldborderSize-100 > 100) {
+ running = true;
+ broadcastMessage(worldborderPrefix + message("WORLDBORDER_DECREASING"));
+ currentWorldborderSize -= 100;
+ World world = Bukkit.getWorld("hideandseek_"+spawnWorld);
+ assert world != null;
+ org.bukkit.WorldBorder border = world.getWorldBorder();
+ border.setSize(border.getSize()-100,30);
+ delay = 30;
+ }
}
+
+ public void resetWorldborder(String worldName) {
+ World world = Bukkit.getWorld(worldName);
+ assert world != null;
+ org.bukkit.WorldBorder border = world.getWorldBorder();
+ if(worldborderEnabled) {
+ border.setSize(worldborderSize);
+ border.setCenter(worldborderPosition.getX(), worldborderPosition.getZ());
+ currentWorldborderSize = worldborderSize;
+ } else {
+ border.setSize(30000000);
+ border.setCenter(0, 0);
+ }
+ }
+
+ public int getDelay(){
+ return delay;
+ }
+
+ public boolean isRunning() {
+ return running;
+ }
+
} \ No newline at end of file