mirror of
https://github.com/garbagemule/MobArena.git
synced 2024-11-23 02:55:46 +01:00
Add support for join, leave, and info signs.
The ability to execute commands by hitting signs is already implemented by other plugins, but by creating built-in support for such signs, it's possible to leverage information about the plugin and its current state. This implementation allows for displaying live information about player counts, waves, etc. on the signs in addition to tying actions to them. Customizable templates defined in the new signs.yml config-file can be bound to signs during the in-game sign creation, and users can define state-specific templates that change based on whether an arena is completely idle, has players in the lobby, or is running and in full swing. Sign data is stored in data/signs.data as a YAML-formatted file that shouldn't be modified directly, effectively separating configuration (templates in signs.yml) and data (coordinates and parameters in signs.data). Closes #385
This commit is contained in:
parent
42416cab2f
commit
84249640d1
@ -674,6 +674,7 @@ public class ArenaMasterImpl implements ArenaMaster
|
||||
plugin.reloadConfig();
|
||||
config = plugin.getConfig();
|
||||
initialize();
|
||||
plugin.reloadSigns();
|
||||
if (wasEnabled) setEnabled(true);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,9 @@ import com.garbagemule.MobArena.listeners.MagicSpellsListener;
|
||||
import com.garbagemule.MobArena.metrics.ArenaCountChart;
|
||||
import com.garbagemule.MobArena.metrics.ClassCountChart;
|
||||
import com.garbagemule.MobArena.metrics.VaultChart;
|
||||
import com.garbagemule.MobArena.signs.ArenaSign;
|
||||
import com.garbagemule.MobArena.signs.SignBootstrap;
|
||||
import com.garbagemule.MobArena.signs.SignListeners;
|
||||
import com.garbagemule.MobArena.things.ThingManager;
|
||||
import com.garbagemule.MobArena.util.VersionChecker;
|
||||
import com.garbagemule.MobArena.util.config.ConfigUtils;
|
||||
@ -18,6 +21,7 @@ import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
@ -52,6 +56,8 @@ public class MobArena extends JavaPlugin
|
||||
private Messenger messenger;
|
||||
private ThingManager thingman;
|
||||
|
||||
private SignListeners signListeners;
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
thingman = new ThingManager(this);
|
||||
@ -61,6 +67,7 @@ public class MobArena extends JavaPlugin
|
||||
// Initialize config-file
|
||||
configFile = new File(getDataFolder(), "config.yml");
|
||||
config = new YamlConfiguration();
|
||||
ConfigurationSerialization.registerClass(ArenaSign.class);
|
||||
reloadConfig();
|
||||
|
||||
// Initialize global messenger
|
||||
@ -88,6 +95,9 @@ public class MobArena extends JavaPlugin
|
||||
arenaMaster = new ArenaMasterImpl(this);
|
||||
arenaMaster.initialize();
|
||||
|
||||
// Load signs after Messenger and ArenaMaster
|
||||
reloadSigns();
|
||||
|
||||
// Register event listeners
|
||||
registerListeners();
|
||||
|
||||
@ -111,6 +121,7 @@ public class MobArena extends JavaPlugin
|
||||
}
|
||||
arenaMaster.resetArenaMap();
|
||||
VersionChecker.shutdown();
|
||||
ConfigurationSerialization.unregisterClass(ArenaSign.class);
|
||||
|
||||
getLogger().info("disabled.");
|
||||
}
|
||||
@ -126,6 +137,16 @@ public class MobArena extends JavaPlugin
|
||||
|
||||
@Override
|
||||
public void reloadConfig() {
|
||||
// Make sure the data folder exists
|
||||
File data = new File(getDataFolder(), "data");
|
||||
if (!data.exists()) {
|
||||
boolean created = data.mkdir();
|
||||
if (!created) {
|
||||
throw new IllegalStateException("Failed to create data folder!");
|
||||
}
|
||||
getLogger().info("Created data folder.");
|
||||
}
|
||||
|
||||
// Check if the config-file exists
|
||||
if (!configFile.exists()) {
|
||||
getLogger().info("No config-file found, creating default...");
|
||||
@ -162,6 +183,15 @@ public class MobArena extends JavaPlugin
|
||||
}
|
||||
}
|
||||
|
||||
void reloadSigns() {
|
||||
if (signListeners != null) {
|
||||
signListeners.unregister();
|
||||
}
|
||||
SignBootstrap bootstrap = SignBootstrap.create(this);
|
||||
signListeners = new SignListeners();
|
||||
signListeners.register(bootstrap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveConfig() {
|
||||
try {
|
||||
|
47
src/main/java/com/garbagemule/MobArena/signs/ArenaSign.java
Normal file
47
src/main/java/com/garbagemule/MobArena/signs/ArenaSign.java
Normal file
@ -0,0 +1,47 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ArenaSign implements ConfigurationSerializable {
|
||||
|
||||
final Location location;
|
||||
final String templateId;
|
||||
final String arenaId;
|
||||
final String type;
|
||||
|
||||
ArenaSign(Location location, String templateId, String arenaId, String type) {
|
||||
this.location = location;
|
||||
this.templateId = templateId;
|
||||
this.arenaId = arenaId;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("location", location);
|
||||
result.put("templateId", templateId);
|
||||
result.put("arenaId", arenaId);
|
||||
result.put("type", type);
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public static ArenaSign deserialize(Map<String, Object> map) {
|
||||
try {
|
||||
Location location = (Location) map.get("location");
|
||||
String templateId = (String) map.get("templateId");
|
||||
String arenaId = (String) map.get("arenaId");
|
||||
String type = (String) map.get("type");
|
||||
return new ArenaSign(location, templateId, arenaId, type);
|
||||
} catch (ClassCastException e) {
|
||||
String msg = "An arena sign in " + SignStore.FILENAME + " is invalid! You may have to delete the file.";
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
class HandlesSignClicks implements Listener {
|
||||
|
||||
private static final long COOLDOWN_TIME = 500;
|
||||
|
||||
private final SignStore signStore;
|
||||
private final InvokesSignAction invokesSignAction;
|
||||
private final Map<UUID, Long> cooldowns;
|
||||
|
||||
HandlesSignClicks(SignStore signStore, InvokesSignAction invokesSignAction) {
|
||||
this.signStore = signStore;
|
||||
this.invokesSignAction = invokesSignAction;
|
||||
this.cooldowns = new HashMap<>();
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void on(PlayerInteractEvent event) {
|
||||
Block block = event.getClickedBlock();
|
||||
if (block == null) {
|
||||
return;
|
||||
}
|
||||
if (!(block.getState() instanceof Sign)) {
|
||||
return;
|
||||
}
|
||||
signStore.findByLocation(block.getLocation())
|
||||
.ifPresent(sign -> purgeAndInvoke(sign, event.getPlayer()));
|
||||
}
|
||||
|
||||
private void purgeAndInvoke(ArenaSign sign, Player player) {
|
||||
long now = System.currentTimeMillis();
|
||||
cooldowns.values().removeIf(time -> time < now);
|
||||
|
||||
cooldowns.computeIfAbsent(player.getUniqueId(), id -> {
|
||||
invokesSignAction.invoke(sign, player);
|
||||
return now + COOLDOWN_TIME;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.SignChangeEvent;
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
class HandlesSignCreation implements Listener {
|
||||
|
||||
private final StoresNewSign storesNewSign;
|
||||
private final RendersTemplateById rendersTemplate;
|
||||
private final Messenger messenger;
|
||||
|
||||
HandlesSignCreation(
|
||||
StoresNewSign storesNewSign,
|
||||
RendersTemplateById rendersTemplate,
|
||||
Messenger messenger
|
||||
) {
|
||||
this.storesNewSign = storesNewSign;
|
||||
this.rendersTemplate = rendersTemplate;
|
||||
this.messenger = messenger;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void on(SignChangeEvent event) {
|
||||
if (!trim(event, 0).equalsIgnoreCase("[MA]")) {
|
||||
return;
|
||||
}
|
||||
|
||||
Location location = event.getBlock().getLocation();
|
||||
String arenaId = trim(event, 1);
|
||||
String signType = trim(event, 2).toLowerCase();
|
||||
String templateId = trim(event, 3).toLowerCase();
|
||||
|
||||
if (templateId.isEmpty()) {
|
||||
templateId = signType;
|
||||
}
|
||||
|
||||
Player player = event.getPlayer();
|
||||
try {
|
||||
storesNewSign.store(location, arenaId, templateId, signType);
|
||||
messenger.tell(player, "New " + signType + " sign created for arena " + arenaId);
|
||||
|
||||
String[] lines = rendersTemplate.render(templateId, arenaId);
|
||||
IntStream.range(0, 4)
|
||||
.forEach(i -> event.setLine(i, lines[i]));
|
||||
} catch (IllegalArgumentException e) {
|
||||
messenger.tell(player, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private String trim(SignChangeEvent event, int index) {
|
||||
String line = event.getLine(index);
|
||||
if (line == null) {
|
||||
return "";
|
||||
}
|
||||
return line.trim();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
|
||||
class HandlesSignDestruction implements Listener {
|
||||
|
||||
private final RemovesSignAtLocation removesSignAtLocation;
|
||||
private final Messenger messenger;
|
||||
|
||||
HandlesSignDestruction(
|
||||
RemovesSignAtLocation removesSignAtLocation,
|
||||
Messenger messenger
|
||||
) {
|
||||
this.removesSignAtLocation = removesSignAtLocation;
|
||||
this.messenger = messenger;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void on(BlockBreakEvent event) {
|
||||
Location location = event.getBlock().getLocation();
|
||||
removesSignAtLocation.remove(location)
|
||||
.ifPresent(sign -> messenger.tell(
|
||||
event.getPlayer(),
|
||||
"Removed " + sign.type + " sign for arena " + sign.arenaId
|
||||
));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import com.garbagemule.MobArena.Msg;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
class InvokesSignAction {
|
||||
|
||||
private final ArenaMaster arenaMaster;
|
||||
private final Messenger messenger;
|
||||
|
||||
InvokesSignAction(ArenaMaster arenaMaster, Messenger messenger) {
|
||||
this.arenaMaster = arenaMaster;
|
||||
this.messenger = messenger;
|
||||
}
|
||||
|
||||
void invoke(ArenaSign sign, Player player) {
|
||||
if (sign.type.equals("join")) {
|
||||
withArena(sign, player, arena -> {
|
||||
if (arena.canJoin(player)) {
|
||||
// Join message is sent in playerJoin
|
||||
arena.playerJoin(player, player.getLocation());
|
||||
}
|
||||
});
|
||||
} else if (sign.type.equals("leave")) {
|
||||
withArena(sign, player, arena -> {
|
||||
if (arena.inArena(player) || arena.inLobby(player) || arena.inSpec(player)) {
|
||||
// Leave message is not sent in playerLeave
|
||||
if (arena.playerLeave(player)) {
|
||||
arena.getMessenger().tell(player, Msg.LEAVE_PLAYER_LEFT);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void withArena(ArenaSign sign, Player player, Consumer<Arena> action) {
|
||||
Arena arena = arenaMaster.getArenaWithName(sign.arenaId);
|
||||
if (arena == null) {
|
||||
messenger.tell(player, "Arena " + sign.arenaId + " not found");
|
||||
return;
|
||||
}
|
||||
action.accept(arena);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class LoadsSignStore {
|
||||
|
||||
private final MobArena plugin;
|
||||
|
||||
LoadsSignStore(MobArena plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
SignStore load() {
|
||||
YamlConfiguration yaml = new YamlConfiguration();
|
||||
try {
|
||||
File data = new File(plugin.getDataFolder(), "data");
|
||||
yaml.load(new File(data, SignStore.FILENAME));
|
||||
} catch (FileNotFoundException e) {
|
||||
return new SignStore(Collections.emptyList());
|
||||
} catch (InvalidConfigurationException e) {
|
||||
String msg = SignStore.FILENAME + " is invalid! You may have to delete it.";
|
||||
throw new IllegalStateException(msg, e);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
List<ArenaSign> signs = yaml.getList("signs").stream()
|
||||
.filter(raw -> raw instanceof ArenaSign)
|
||||
.map(raw -> (ArenaSign) raw)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
plugin.getLogger().info("Loaded " + signs.size() + " arena signs.");
|
||||
|
||||
return new SignStore(signs);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
class LoadsTemplateStore {
|
||||
|
||||
private final MobArena plugin;
|
||||
|
||||
LoadsTemplateStore(MobArena plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
TemplateStore read() {
|
||||
YamlConfiguration yaml = new YamlConfiguration();
|
||||
try {
|
||||
File file = new File(plugin.getDataFolder(), TemplateStore.FILENAME);
|
||||
if (!file.exists()) {
|
||||
plugin.getLogger().info(TemplateStore.FILENAME + " not found, creating default...");
|
||||
plugin.saveResource(TemplateStore.FILENAME, false);
|
||||
}
|
||||
yaml.load(file);
|
||||
} catch (InvalidConfigurationException e) {
|
||||
throw new IllegalStateException(TemplateStore.FILENAME + " is invalid!", e);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new IllegalStateException(TemplateStore.FILENAME + " is missing!", e);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
Map<String, Template> map = new HashMap<>();
|
||||
for (String key : yaml.getKeys(false)) {
|
||||
validateTemplateNode(key, yaml);
|
||||
String templateId = stripStateSuffix(key);
|
||||
map.computeIfAbsent(templateId, id -> loadTemplate(id, yaml));
|
||||
}
|
||||
|
||||
plugin.getLogger().info("Loaded " + map.size() + " sign templates.");
|
||||
|
||||
return new TemplateStore(map);
|
||||
}
|
||||
|
||||
private void validateTemplateNode(String key, YamlConfiguration yaml) {
|
||||
List<?> list = yaml.getList(key);
|
||||
if (list == null) {
|
||||
String msg = "Template " + key + " in " + TemplateStore.FILENAME + " is not a list!";
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
list.forEach(element -> {
|
||||
if (!(element instanceof String)) {
|
||||
String msg = "Template " + key + " in " + TemplateStore.FILENAME + " is not a valid list of strings!";
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String stripStateSuffix(String id) {
|
||||
if (hasStateSuffix(id)) {
|
||||
return id.split("-", -1)[0];
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
private boolean hasStateSuffix(String id) {
|
||||
return id.endsWith("-idle")
|
||||
|| id.endsWith("-joining")
|
||||
|| id.endsWith("-running");
|
||||
}
|
||||
|
||||
private Template loadTemplate(String id, YamlConfiguration yaml) {
|
||||
String[] base = getLines(yaml, id);
|
||||
String[] idle = getLines(yaml, id + "-idle");
|
||||
String[] joining = getLines(yaml, id + "-joining");
|
||||
String[] running = getLines(yaml, id + "-running");
|
||||
|
||||
return new Template.Builder(id)
|
||||
.withBase(base)
|
||||
.withIdle(idle)
|
||||
.withJoining(joining)
|
||||
.withRunning(running)
|
||||
.build();
|
||||
}
|
||||
|
||||
private String[] getLines(YamlConfiguration config, String id) {
|
||||
List<String> list = config.getStringList(id);
|
||||
if (list.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
while (list.size() < 4) {
|
||||
list.add("");
|
||||
}
|
||||
if (list.size() > 4) {
|
||||
list = list.subList(0, 4);
|
||||
}
|
||||
return list.toArray(new String[0]);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class RedrawsArenaSigns {
|
||||
|
||||
private final SignStore signStore;
|
||||
private final TemplateStore templateStore;
|
||||
private final RendersTemplate rendersTemplate;
|
||||
private final SetsLines setsSignLines;
|
||||
|
||||
RedrawsArenaSigns(
|
||||
SignStore signStore,
|
||||
TemplateStore templateStore,
|
||||
RendersTemplate rendersTemplate,
|
||||
SetsLines setsSignLines
|
||||
) {
|
||||
this.signStore = signStore;
|
||||
this.templateStore = templateStore;
|
||||
this.rendersTemplate = rendersTemplate;
|
||||
this.setsSignLines = setsSignLines;
|
||||
}
|
||||
|
||||
void redraw(Arena arena) {
|
||||
List<ArenaSign> signs = signStore.findByArenaId(arena.configName());
|
||||
|
||||
Map<String, String[]> rendered = signs.stream()
|
||||
.map(sign -> sign.templateId)
|
||||
.distinct()
|
||||
.collect(Collectors.toMap(
|
||||
templateId -> templateId,
|
||||
templateId -> render(templateId, arena)
|
||||
));
|
||||
|
||||
signs.forEach(sign -> setsSignLines.set(
|
||||
sign.location,
|
||||
rendered.get(sign.templateId)
|
||||
));
|
||||
}
|
||||
|
||||
private String[] render(String templateId, Arena arena) {
|
||||
return templateStore.findById(templateId)
|
||||
.map(template -> rendersTemplate.render(template, arena))
|
||||
.orElseGet(() -> notFound(templateId));
|
||||
}
|
||||
|
||||
private static String[] notFound(String templateId) {
|
||||
return new String[]{
|
||||
String.join(ChatColor.MAGIC + "b" + ChatColor.RESET, "BROKEN".split("")),
|
||||
"Template",
|
||||
ChatColor.BOLD + templateId,
|
||||
"not found! :("
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import com.garbagemule.MobArena.events.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
|
||||
class RedrawsSignsOnUpdates implements Listener {
|
||||
|
||||
private final RedrawsArenaSigns redrawsArenaSigns;
|
||||
private final BukkitScheduler scheduler;
|
||||
private final MobArena plugin;
|
||||
|
||||
RedrawsSignsOnUpdates(
|
||||
RedrawsArenaSigns redrawsArenaSigns,
|
||||
MobArena plugin
|
||||
) {
|
||||
this.redrawsArenaSigns = redrawsArenaSigns;
|
||||
this.scheduler = plugin.getServer().getScheduler();
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void on(ArenaPlayerJoinEvent event) {
|
||||
handle(event.getArena());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void on(ArenaPlayerLeaveEvent event) {
|
||||
handle(event.getArena());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void on(ArenaPlayerReadyEvent event) {
|
||||
handle(event.getArena());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void on(ArenaStartEvent event) {
|
||||
handle(event.getArena());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void on(NewWaveEvent event) {
|
||||
handle(event.getArena());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void on(ArenaPlayerDeathEvent event) {
|
||||
handle(event.getArena());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void on(ArenaEndEvent event) {
|
||||
handle(event.getArena());
|
||||
}
|
||||
|
||||
private void handle(Arena arena) {
|
||||
scheduler.runTask(plugin, () -> redrawsArenaSigns.redraw(arena));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
class RemovesSignAtLocation {
|
||||
|
||||
private final SignStore signStore;
|
||||
private final SavesSignStore savesSignStore;
|
||||
|
||||
RemovesSignAtLocation(
|
||||
SignStore signStore,
|
||||
SavesSignStore savesSignStore
|
||||
) {
|
||||
this.signStore = signStore;
|
||||
this.savesSignStore = savesSignStore;
|
||||
}
|
||||
|
||||
Optional<ArenaSign> remove(Location location) {
|
||||
Optional<ArenaSign> sign = signStore.remove(location);
|
||||
sign.ifPresent(s -> savesSignStore.save(signStore));
|
||||
return sign;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import static java.lang.String.valueOf;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
class RendersTemplate {
|
||||
|
||||
String[] render(Template template, Arena arena) {
|
||||
String[] lines = getTemplateByState(template, arena);
|
||||
|
||||
String[] result = new String[lines.length];
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
String rendered = render(lines[i], arena);
|
||||
result[i] = truncate(rendered);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String[] getTemplateByState(Template template, Arena arena) {
|
||||
if (arena.isRunning()) {
|
||||
return template.running;
|
||||
}
|
||||
if (arena.getPlayersInLobby().size() > 0) {
|
||||
return template.joining;
|
||||
}
|
||||
return template.idle;
|
||||
}
|
||||
|
||||
private String render(String line, Arena arena) {
|
||||
String result = generic(line, arena);
|
||||
if (arena.isRunning()) {
|
||||
result = running(result, arena);
|
||||
} else {
|
||||
result = joining(result, arena);
|
||||
}
|
||||
return ChatColor.translateAlternateColorCodes('&', result);
|
||||
}
|
||||
|
||||
private String generic(String line, Arena arena) {
|
||||
return line
|
||||
.replace("<arena-name>", arena.configName())
|
||||
.replace("<min-players>", valueOf(arena.getMinPlayers()))
|
||||
.replace("<max-players>", valueOf(arena.getMaxPlayers()));
|
||||
}
|
||||
|
||||
private String running(String line, Arena arena) {
|
||||
return line
|
||||
.replace("<initial-players>", valueOf(arena.getPlayerCount()))
|
||||
.replace("<live-players>", valueOf(arena.getPlayersInArena().size()))
|
||||
.replace("<dead-players>", valueOf(arena.getPlayerCount() - arena.getPlayersInArena().size()))
|
||||
.replace("<current-wave>", valueOf(arena.getWaveManager().getWaveNumber()))
|
||||
.replace("<final-wave>", valueOf(arena.getWaveManager().getFinalWave()))
|
||||
.replace("<lobby-players>", "-")
|
||||
.replace("<ready-players>", "-");
|
||||
}
|
||||
|
||||
private String joining(String line, Arena arena) {
|
||||
return line
|
||||
.replace("<initial-players>", valueOf(arena.getPlayersInLobby().size()))
|
||||
.replace("<live-players>", valueOf(arena.getPlayersInLobby().size()))
|
||||
.replace("<dead-players>", "-")
|
||||
.replace("<current-wave>", "-")
|
||||
.replace("<lobby-players>", valueOf(arena.getPlayersInLobby().size()))
|
||||
.replace("<ready-players>", valueOf(arena.getReadyPlayersInLobby().size()));
|
||||
}
|
||||
|
||||
private String truncate(String rendered) {
|
||||
if (rendered.length() <= 15) {
|
||||
return rendered;
|
||||
}
|
||||
return rendered.substring(0, 15);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
class RendersTemplateById {
|
||||
|
||||
private final ArenaMaster arenaMaster;
|
||||
private final TemplateStore templateStore;
|
||||
private final RendersTemplate rendersTemplate;
|
||||
|
||||
RendersTemplateById(
|
||||
ArenaMaster arenaMaster,
|
||||
TemplateStore templateStore,
|
||||
RendersTemplate rendersTemplate
|
||||
) {
|
||||
this.arenaMaster = arenaMaster;
|
||||
this.templateStore = templateStore;
|
||||
this.rendersTemplate = rendersTemplate;
|
||||
}
|
||||
|
||||
String[] render(String templateId, String arenaId) {
|
||||
Template template = templateStore.findById(templateId)
|
||||
.orElseThrow(() -> new IllegalArgumentException(
|
||||
"Template " + templateId + " not found"
|
||||
));
|
||||
|
||||
Arena arena = arenaMaster.getArenaWithName(arenaId);
|
||||
if (arena == null) {
|
||||
throw new IllegalStateException("Arena " + arenaId + " not found");
|
||||
}
|
||||
|
||||
return rendersTemplate.render(template, arena);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class SavesSignStore {
|
||||
|
||||
private final MobArena plugin;
|
||||
|
||||
SavesSignStore(MobArena plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
void save(SignStore signStore) {
|
||||
YamlConfiguration yaml = new YamlConfiguration();
|
||||
List<ArenaSign> values = new ArrayList<>(signStore.findAll());
|
||||
yaml.set("signs", values);
|
||||
try {
|
||||
File data = new File(plugin.getDataFolder(), "data");
|
||||
yaml.options().header("MobArena Sign Store\n\nPlease DON'T edit this file by hand!\n");
|
||||
yaml.save(new File(data, SignStore.FILENAME));
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
22
src/main/java/com/garbagemule/MobArena/signs/SetsLines.java
Normal file
22
src/main/java/com/garbagemule/MobArena/signs/SetsLines.java
Normal file
@ -0,0 +1,22 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.Sign;
|
||||
|
||||
class SetsLines {
|
||||
|
||||
void set(Location location, String[] lines) {
|
||||
BlockState state = location.getBlock().getState();
|
||||
if (!(state instanceof Sign)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Sign sign = (Sign) state;
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
sign.setLine(i, lines[i]);
|
||||
}
|
||||
sign.update();
|
||||
}
|
||||
|
||||
}
|
130
src/main/java/com/garbagemule/MobArena/signs/SignBootstrap.java
Normal file
130
src/main/java/com/garbagemule/MobArena/signs/SignBootstrap.java
Normal file
@ -0,0 +1,130 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class SignBootstrap {
|
||||
|
||||
private final MobArena plugin;
|
||||
private final SignStore signStore;
|
||||
private final TemplateStore templateStore;
|
||||
|
||||
private InvokesSignAction invokesSignAction;
|
||||
private RedrawsArenaSigns redrawsArenaSigns;
|
||||
private RemovesSignAtLocation removesSignAtLocation;
|
||||
private RendersTemplate rendersTemplate;
|
||||
private RendersTemplateById rendersTemplateById;
|
||||
private SetsLines setsLines;
|
||||
private StoresNewSign storesNewSign;
|
||||
private SavesSignStore savesSignStore;
|
||||
|
||||
private SignBootstrap(
|
||||
MobArena plugin,
|
||||
SignStore signStore,
|
||||
TemplateStore templateStore
|
||||
) {
|
||||
this.plugin = plugin;
|
||||
this.signStore = signStore;
|
||||
this.templateStore = templateStore;
|
||||
}
|
||||
|
||||
MobArena getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
SignStore getSignStore() {
|
||||
return signStore;
|
||||
}
|
||||
|
||||
TemplateStore getTemplateStore() {
|
||||
return templateStore;
|
||||
}
|
||||
|
||||
InvokesSignAction getInvokesSignAction() {
|
||||
if (invokesSignAction == null) {
|
||||
invokesSignAction = new InvokesSignAction(
|
||||
plugin.getArenaMaster(),
|
||||
plugin.getGlobalMessenger()
|
||||
);
|
||||
}
|
||||
return invokesSignAction;
|
||||
}
|
||||
|
||||
RedrawsArenaSigns getRedrawsArenaSigns() {
|
||||
if (redrawsArenaSigns == null) {
|
||||
redrawsArenaSigns = new RedrawsArenaSigns(
|
||||
getSignStore(),
|
||||
getTemplateStore(),
|
||||
getRendersTemplate(),
|
||||
getSetsLines()
|
||||
);
|
||||
}
|
||||
return redrawsArenaSigns;
|
||||
}
|
||||
|
||||
RemovesSignAtLocation getRemovesSignAtLocation() {
|
||||
if (removesSignAtLocation == null) {
|
||||
removesSignAtLocation = new RemovesSignAtLocation(
|
||||
getSignStore(),
|
||||
getSavesSignStore()
|
||||
);
|
||||
}
|
||||
return removesSignAtLocation;
|
||||
}
|
||||
|
||||
RendersTemplate getRendersTemplate() {
|
||||
if (rendersTemplate == null) {
|
||||
rendersTemplate = new RendersTemplate();
|
||||
}
|
||||
return rendersTemplate;
|
||||
}
|
||||
|
||||
RendersTemplateById getRendersTemplateById() {
|
||||
if (rendersTemplateById == null) {
|
||||
rendersTemplateById = new RendersTemplateById(
|
||||
plugin.getArenaMaster(),
|
||||
getTemplateStore(),
|
||||
getRendersTemplate()
|
||||
);
|
||||
}
|
||||
return rendersTemplateById;
|
||||
}
|
||||
|
||||
SetsLines getSetsLines() {
|
||||
if (setsLines == null) {
|
||||
setsLines = new SetsLines();
|
||||
}
|
||||
return setsLines;
|
||||
}
|
||||
|
||||
StoresNewSign getStoresNewSign() {
|
||||
if (storesNewSign == null) {
|
||||
storesNewSign = new StoresNewSign(
|
||||
plugin.getArenaMaster(),
|
||||
getTemplateStore(),
|
||||
getSignStore(),
|
||||
getSavesSignStore()
|
||||
);
|
||||
}
|
||||
return storesNewSign;
|
||||
}
|
||||
|
||||
SavesSignStore getSavesSignStore() {
|
||||
if (savesSignStore == null) {
|
||||
savesSignStore = new SavesSignStore(plugin);
|
||||
}
|
||||
return savesSignStore;
|
||||
}
|
||||
|
||||
public static SignBootstrap create(MobArena plugin) {
|
||||
TemplateStore templateStore = new LoadsTemplateStore(plugin).read();
|
||||
SignStore signStore = new LoadsSignStore(plugin).load();
|
||||
|
||||
SignBootstrap bootstrap = new SignBootstrap(plugin, signStore, templateStore);
|
||||
|
||||
plugin.getArenaMaster().getArenas()
|
||||
.forEach(bootstrap.getRedrawsArenaSigns()::redraw);
|
||||
|
||||
return bootstrap;
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SignListeners {
|
||||
|
||||
private final List<Listener> listeners;
|
||||
|
||||
public SignListeners() {
|
||||
this.listeners = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void register(SignBootstrap bootstrap) {
|
||||
listeners.add(clicks(bootstrap));
|
||||
listeners.add(creation(bootstrap));
|
||||
listeners.add(destruction(bootstrap));
|
||||
listeners.add(redraw(bootstrap));
|
||||
|
||||
listeners.forEach(listener -> register(listener, bootstrap));
|
||||
}
|
||||
|
||||
private HandlesSignClicks clicks(SignBootstrap bootstrap) {
|
||||
return new HandlesSignClicks(
|
||||
bootstrap.getSignStore(),
|
||||
bootstrap.getInvokesSignAction()
|
||||
);
|
||||
}
|
||||
|
||||
private HandlesSignCreation creation(SignBootstrap bootstrap) {
|
||||
return new HandlesSignCreation(
|
||||
bootstrap.getStoresNewSign(),
|
||||
bootstrap.getRendersTemplateById(),
|
||||
bootstrap.getPlugin().getGlobalMessenger()
|
||||
);
|
||||
}
|
||||
|
||||
private HandlesSignDestruction destruction(SignBootstrap bootstrap) {
|
||||
return new HandlesSignDestruction(
|
||||
bootstrap.getRemovesSignAtLocation(),
|
||||
bootstrap.getPlugin().getGlobalMessenger()
|
||||
);
|
||||
}
|
||||
|
||||
private RedrawsSignsOnUpdates redraw(SignBootstrap bootstrap) {
|
||||
return new RedrawsSignsOnUpdates(
|
||||
bootstrap.getRedrawsArenaSigns(),
|
||||
bootstrap.getPlugin()
|
||||
);
|
||||
}
|
||||
|
||||
private void register(Listener listener, SignBootstrap bootstrap) {
|
||||
MobArena plugin = bootstrap.getPlugin();
|
||||
plugin.getServer().getPluginManager().registerEvents(listener, plugin);
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
listeners.forEach(HandlerList::unregisterAll);
|
||||
listeners.clear();
|
||||
}
|
||||
|
||||
}
|
49
src/main/java/com/garbagemule/MobArena/signs/SignStore.java
Normal file
49
src/main/java/com/garbagemule/MobArena/signs/SignStore.java
Normal file
@ -0,0 +1,49 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class SignStore {
|
||||
|
||||
static final String FILENAME = "signs.data";
|
||||
|
||||
private final Map<Location, ArenaSign> signs;
|
||||
|
||||
SignStore(List<ArenaSign> signs) {
|
||||
this.signs = signs.stream()
|
||||
.collect(Collectors.toMap(
|
||||
sign -> sign.location,
|
||||
sign -> sign
|
||||
));
|
||||
}
|
||||
|
||||
void store(ArenaSign sign) {
|
||||
signs.put(sign.location, sign);
|
||||
}
|
||||
|
||||
Optional<ArenaSign> remove(Location location) {
|
||||
ArenaSign sign = signs.remove(location);
|
||||
return Optional.ofNullable(sign);
|
||||
}
|
||||
|
||||
Collection<ArenaSign> findAll() {
|
||||
return signs.values();
|
||||
}
|
||||
|
||||
Optional<ArenaSign> findByLocation(Location location) {
|
||||
ArenaSign sign = signs.get(location);
|
||||
return Optional.ofNullable(sign);
|
||||
}
|
||||
|
||||
List<ArenaSign> findByArenaId(String arenaId) {
|
||||
return signs.values().stream()
|
||||
.filter(sign -> sign.arenaId.equals(arenaId))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import org.bukkit.Location;
|
||||
|
||||
class StoresNewSign {
|
||||
|
||||
private final ArenaMaster arenaMaster;
|
||||
private final TemplateStore templateStore;
|
||||
private final SignStore signStore;
|
||||
private final SavesSignStore savesSignStore;
|
||||
|
||||
StoresNewSign(
|
||||
ArenaMaster arenaMaster,
|
||||
TemplateStore templateStore,
|
||||
SignStore signStore,
|
||||
SavesSignStore savesSignStore
|
||||
) {
|
||||
this.arenaMaster = arenaMaster;
|
||||
this.templateStore = templateStore;
|
||||
this.signStore = signStore;
|
||||
this.savesSignStore = savesSignStore;
|
||||
}
|
||||
|
||||
void store(
|
||||
Location location,
|
||||
String arenaId,
|
||||
String templateId,
|
||||
String signType
|
||||
) {
|
||||
Arena arena = arenaMaster.getArenaWithName(arenaId);
|
||||
if (arena == null) {
|
||||
throw new IllegalArgumentException("Arena " + arenaId + " not found");
|
||||
}
|
||||
|
||||
templateStore.findById(templateId)
|
||||
.orElseThrow(() -> new IllegalArgumentException(
|
||||
"Template " + templateId + " not found"
|
||||
));
|
||||
|
||||
switch (signType) {
|
||||
case "info":
|
||||
case "join":
|
||||
case "leave":
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid sign type: " + signType);
|
||||
}
|
||||
|
||||
signStore.store(new ArenaSign(location, templateId, arenaId, signType));
|
||||
|
||||
savesSignStore.save(signStore);
|
||||
}
|
||||
|
||||
}
|
78
src/main/java/com/garbagemule/MobArena/signs/Template.java
Normal file
78
src/main/java/com/garbagemule/MobArena/signs/Template.java
Normal file
@ -0,0 +1,78 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
class Template {
|
||||
|
||||
final String[] idle;
|
||||
final String[] joining;
|
||||
final String[] running;
|
||||
|
||||
private Template(String[] idle, String[] joining, String[] running) {
|
||||
this.idle = idle;
|
||||
this.joining = joining;
|
||||
this.running = running;
|
||||
}
|
||||
|
||||
static class Builder {
|
||||
|
||||
private String id;
|
||||
private String[] base;
|
||||
private String[] idle;
|
||||
private String[] joining;
|
||||
private String[] running;
|
||||
|
||||
Builder(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
Builder withBase(String[] lines) {
|
||||
this.base = lines;
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder withIdle(String[] lines) {
|
||||
this.idle = lines;
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder withJoining(String[] lines) {
|
||||
this.joining = lines;
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder withRunning(String[] lines) {
|
||||
this.running = lines;
|
||||
return this;
|
||||
}
|
||||
|
||||
Template build() {
|
||||
if (base == null) {
|
||||
if (idle == null) {
|
||||
missing("idle");
|
||||
}
|
||||
if (joining == null) {
|
||||
missing("joining");
|
||||
}
|
||||
if (running == null) {
|
||||
missing("running");
|
||||
}
|
||||
}
|
||||
if (idle == null) {
|
||||
idle = base;
|
||||
}
|
||||
if (joining == null) {
|
||||
joining = base;
|
||||
}
|
||||
if (running == null) {
|
||||
running = base;
|
||||
}
|
||||
return new Template(idle, joining, running);
|
||||
}
|
||||
|
||||
private void missing(String state) {
|
||||
String msg = "Missing either base template '" + id + "' or state template '" + id + "-" + state + "'";
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
class TemplateStore {
|
||||
|
||||
static final String FILENAME = "signs.yml";
|
||||
|
||||
private final Map<String, Template> templates;
|
||||
|
||||
TemplateStore(Map<String, Template> templates) {
|
||||
this.templates = templates;
|
||||
}
|
||||
|
||||
Optional<Template> findById(String templateId) {
|
||||
Template template = templates.get(templateId);
|
||||
return Optional.ofNullable(template);
|
||||
}
|
||||
|
||||
}
|
55
src/main/resources/signs.yml
Normal file
55
src/main/resources/signs.yml
Normal file
@ -0,0 +1,55 @@
|
||||
# MobArena Sign Templates
|
||||
#
|
||||
# Use this file to set up sign templates for use in MobArena. All of
|
||||
# the templates in this file can be used for any of the three sign
|
||||
# types (info, join, leave).
|
||||
#
|
||||
# Here is an example of a template:
|
||||
#
|
||||
# potato:
|
||||
# - '<arena-name>'
|
||||
# - '---------------'
|
||||
# - 'Hit the sign to'
|
||||
# - 'join the arena!'
|
||||
#
|
||||
# The template ID is 'potato', and the template uses the <arena-name>
|
||||
# variable, which is translated into the name of the arena. To use the
|
||||
# template in a join sign for an arena called 'castle', just place a
|
||||
# sign in-game with the following lines:
|
||||
#
|
||||
# [MA] <-- needed by MobArena
|
||||
# castle <-- arena name
|
||||
# join <-- sign type
|
||||
# potato <-- template (optional)
|
||||
#
|
||||
# For detailed information about the available variables and the state
|
||||
# suffixes (-idle, -joining, -running), please visit the documentation.
|
||||
|
||||
info-idle:
|
||||
- '&a<arena-name>'
|
||||
- '---------------'
|
||||
- 'Waiting for'
|
||||
- 'players to join'
|
||||
info-joining:
|
||||
- '&a<arena-name>'
|
||||
- '---------------'
|
||||
- 'Ready: <ready-players>/<lobby-players>'
|
||||
info-running:
|
||||
- '&a<arena-name>'
|
||||
- '---------------'
|
||||
- 'Wave: <current-wave>'
|
||||
- 'Alive: <live-players>/<initial-players>'
|
||||
|
||||
join:
|
||||
- '&a<arena-name>'
|
||||
- '---------------'
|
||||
- 'Hit to join'
|
||||
join-running:
|
||||
- '&a<arena-name>'
|
||||
- '---------------'
|
||||
- 'In progress'
|
||||
|
||||
leave:
|
||||
- '&a<arena-name>'
|
||||
- '---------------'
|
||||
- 'Hit to leave'
|
@ -0,0 +1,57 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.StrictStubs.class)
|
||||
public class ArenaSignTest {
|
||||
|
||||
@Test
|
||||
public void serialize() {
|
||||
World world = mock(World.class);
|
||||
Location location = new Location(world, 1, 2, 3);
|
||||
String templateId = "a good template";
|
||||
String arenaId = "cool arena";
|
||||
String type = "join";
|
||||
ArenaSign sign = new ArenaSign(location, templateId, arenaId, type);
|
||||
|
||||
Map<String, Object> result = sign.serialize();
|
||||
|
||||
assertThat(result.get("location"), equalTo(location));
|
||||
assertThat(result.get("templateId"), equalTo(templateId));
|
||||
assertThat(result.get("arenaId"), equalTo(arenaId));
|
||||
assertThat(result.get("type"), equalTo(type));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserialize() {
|
||||
World world = mock(World.class);
|
||||
Location location = new Location(world, 1, 2, 3);
|
||||
String templateId = "a good template";
|
||||
String arenaId = "cool arena";
|
||||
String type = "join";
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("location", location);
|
||||
map.put("templateId", templateId);
|
||||
map.put("arenaId", arenaId);
|
||||
map.put("type", type);
|
||||
|
||||
ArenaSign result = ArenaSign.deserialize(map);
|
||||
|
||||
assertThat(result.location, is(equalTo(location)));
|
||||
assertThat(result.templateId, is(equalTo(templateId)));
|
||||
assertThat(result.arenaId, is(equalTo(arenaId)));
|
||||
assertThat(result.type, is(equalTo(type)));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Chest;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@RunWith(MockitoJUnitRunner.StrictStubs.class)
|
||||
public class HandlesSignClicksTest {
|
||||
|
||||
SignStore signStore;
|
||||
InvokesSignAction invokesSignAction;
|
||||
|
||||
HandlesSignClicks subject;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
signStore = mock(SignStore.class);
|
||||
when(signStore.findByLocation(any()))
|
||||
.thenReturn(Optional.empty());
|
||||
invokesSignAction = mock(InvokesSignAction.class);
|
||||
|
||||
subject = new HandlesSignClicks(signStore, invokesSignAction);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noBlockNoFun() {
|
||||
PlayerInteractEvent event = event(null, null);
|
||||
|
||||
subject.on(event);
|
||||
|
||||
verifyZeroInteractions(signStore);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noSignBlockNoFun() {
|
||||
Block block = mock(Block.class);
|
||||
when(block.getState()).thenReturn(mock(Chest.class));
|
||||
PlayerInteractEvent event = event(null, block);
|
||||
|
||||
subject.on(event);
|
||||
|
||||
verifyZeroInteractions(signStore);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonArenaSignNoFun() {
|
||||
Block block = mock(Block.class);
|
||||
when(block.getState()).thenReturn(mock(Sign.class));
|
||||
PlayerInteractEvent event = event(null, block);
|
||||
|
||||
subject.on(event);
|
||||
|
||||
verifyZeroInteractions(signStore);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arenaSignInvokesAction() {
|
||||
Location location = mock(Location.class);
|
||||
Block block = mock(Block.class);
|
||||
when(block.getLocation()).thenReturn(location);
|
||||
when(block.getState()).thenReturn(mock(Sign.class));
|
||||
ArenaSign sign = new ArenaSign(location, "", "", "");
|
||||
when(signStore.findByLocation(location))
|
||||
.thenReturn(Optional.of(sign));
|
||||
Player player = mock(Player.class);
|
||||
PlayerInteractEvent event = event(player, block);
|
||||
|
||||
subject.on(event);
|
||||
|
||||
verify(invokesSignAction).invoke(sign, player);
|
||||
}
|
||||
|
||||
private PlayerInteractEvent event(Player player, Block block) {
|
||||
return new PlayerInteractEvent(player, null, null, block, null);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.SignChangeEvent;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@RunWith(MockitoJUnitRunner.StrictStubs.class)
|
||||
public class HandlesSignCreationTest {
|
||||
|
||||
StoresNewSign storesNewSign;
|
||||
RendersTemplateById rendersTemplate;
|
||||
Messenger messenger;
|
||||
|
||||
HandlesSignCreation subject;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
storesNewSign = mock(StoresNewSign.class);
|
||||
|
||||
rendersTemplate = mock(RendersTemplateById.class);
|
||||
when(rendersTemplate.render(any(), any()))
|
||||
.thenReturn(new String[]{"", "", "", ""});
|
||||
|
||||
messenger = mock(Messenger.class);
|
||||
|
||||
subject = new HandlesSignCreation(
|
||||
storesNewSign,
|
||||
rendersTemplate,
|
||||
messenger
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noHeaderNoAction() {
|
||||
String[] lines = {"why", "so", "serious", "?"};
|
||||
SignChangeEvent event = event(lines, null);
|
||||
|
||||
subject.on(event);
|
||||
|
||||
verifyZeroInteractions(storesNewSign, rendersTemplate, messenger);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullLinesHandledGracefully() {
|
||||
String[] lines = {"[MA]", null, null, null};
|
||||
SignChangeEvent event = event(lines, null);
|
||||
|
||||
subject.on(event);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useSignTypeIfTemplateNotAvailable() {
|
||||
String arenaId = "castle";
|
||||
String type = "join";
|
||||
String[] lines = {"[MA]", arenaId, type, null};
|
||||
Location location = mock(Location.class);
|
||||
SignChangeEvent event = event(lines, location);
|
||||
|
||||
subject.on(event);
|
||||
|
||||
verify(storesNewSign).store(location, arenaId, type, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useTemplateIfAvailable() {
|
||||
String arenaId = "castle";
|
||||
String type = "join";
|
||||
String templateId = "potato";
|
||||
String[] lines = {"[MA]", arenaId, type, templateId};
|
||||
Location location = mock(Location.class);
|
||||
SignChangeEvent event = event(lines, location);
|
||||
|
||||
subject.on(event);
|
||||
|
||||
verify(storesNewSign).store(location, arenaId, templateId, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeIsLowercased() {
|
||||
String type = "JOIN";
|
||||
String[] lines = {"[MA]", "", type, ""};
|
||||
SignChangeEvent event = event(lines, null);
|
||||
|
||||
subject.on(event);
|
||||
|
||||
String lower = type.toLowerCase();
|
||||
verify(storesNewSign).store(any(), any(), any(), eq(lower));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void templateIdIsLowercased() {
|
||||
String templateId = "BEST-TEMPLATE";
|
||||
String[] lines = {"[MA]", "", "", templateId};
|
||||
SignChangeEvent event = event(lines, null);
|
||||
|
||||
subject.on(event);
|
||||
|
||||
String lower = templateId.toLowerCase();
|
||||
verify(storesNewSign).store(any(), any(), eq(lower), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rendersTemplateAfterStoring() {
|
||||
String arenaId = "castle";
|
||||
String type = "join";
|
||||
String templateId = "potato";
|
||||
String[] lines = {"[MA]", arenaId, type, templateId};
|
||||
Location location = mock(Location.class);
|
||||
SignChangeEvent event = event(lines, location);
|
||||
|
||||
subject.on(event);
|
||||
|
||||
verify(rendersTemplate).render(templateId, arenaId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void errorPassedToMessenger() {
|
||||
String msg = "you messed up";
|
||||
doThrow(new IllegalArgumentException(msg))
|
||||
.when(storesNewSign).store(any(), any(), any(), any());
|
||||
String[] lines = {"[MA]", "", "", ""};
|
||||
SignChangeEvent event = event(lines, null);
|
||||
|
||||
subject.on(event);
|
||||
|
||||
verifyZeroInteractions(rendersTemplate);
|
||||
verify(messenger).tell(event.getPlayer(), msg);
|
||||
}
|
||||
|
||||
private SignChangeEvent event(String[] lines, Location location) {
|
||||
Block block = mock(Block.class);
|
||||
when(block.getLocation()).thenReturn(location);
|
||||
Player player = mock(Player.class);
|
||||
return new SignChangeEvent(block, player, lines);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@RunWith(MockitoJUnitRunner.StrictStubs.class)
|
||||
public class HandlesSignDestructionTest {
|
||||
|
||||
RemovesSignAtLocation removesSignAtLocation;
|
||||
Messenger messenger;
|
||||
|
||||
HandlesSignDestruction subject;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
removesSignAtLocation = mock(RemovesSignAtLocation.class);
|
||||
messenger = mock(Messenger.class);
|
||||
|
||||
subject = new HandlesSignDestruction(
|
||||
removesSignAtLocation,
|
||||
messenger
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNothingWithNonArenaSign() {
|
||||
Block block = mock(Block.class);
|
||||
Player player = mock(Player.class);
|
||||
when(removesSignAtLocation.remove(any()))
|
||||
.thenReturn(Optional.empty());
|
||||
BlockBreakEvent event = new BlockBreakEvent(block, player);
|
||||
|
||||
subject.on(event);
|
||||
|
||||
verifyZeroInteractions(messenger);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reportsBreakageWithArenaSign() {
|
||||
Block block = mock(Block.class);
|
||||
Player player = mock(Player.class);
|
||||
ArenaSign sign = new ArenaSign(null, "", "", "");
|
||||
when(removesSignAtLocation.remove(any()))
|
||||
.thenReturn(Optional.of(sign));
|
||||
BlockBreakEvent event = new BlockBreakEvent(block, player);
|
||||
|
||||
subject.on(event);
|
||||
|
||||
verify(messenger).tell(eq(player), anyString());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@RunWith(MockitoJUnitRunner.StrictStubs.class)
|
||||
public class InvokesSignActionTest {
|
||||
|
||||
ArenaMaster arenaMaster;
|
||||
Messenger messenger;
|
||||
|
||||
InvokesSignAction subject;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
arenaMaster = mock(ArenaMaster.class);
|
||||
messenger = mock(Messenger.class);
|
||||
|
||||
subject = new InvokesSignAction(arenaMaster, messenger);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void infoSignDoesNothing() {
|
||||
String arenaId = "castle";
|
||||
ArenaSign sign = new ArenaSign(null, "", arenaId, "info");
|
||||
Player player = mock(Player.class);
|
||||
|
||||
subject.invoke(sign, player);
|
||||
|
||||
verifyZeroInteractions(arenaMaster);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void joinSignCallsCanJoin() {
|
||||
String arenaId = "castle";
|
||||
ArenaSign sign = new ArenaSign(null, "", arenaId, "join");
|
||||
Player player = mock(Player.class);
|
||||
Arena arena = mock(Arena.class);
|
||||
when(arenaMaster.getArenaWithName(arenaId))
|
||||
.thenReturn(arena);
|
||||
|
||||
subject.invoke(sign, player);
|
||||
|
||||
verify(arena).canJoin(player);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void joinSignCallsPlayerJoin() {
|
||||
String arenaId = "castle";
|
||||
ArenaSign sign = new ArenaSign(null, "", arenaId, "join");
|
||||
Player player = mock(Player.class);
|
||||
Arena arena = mock(Arena.class);
|
||||
when(arena.canJoin(player)).thenReturn(true);
|
||||
when(arenaMaster.getArenaWithName(arenaId))
|
||||
.thenReturn(arena);
|
||||
|
||||
subject.invoke(sign, player);
|
||||
|
||||
verify(arena).playerJoin(eq(player), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void leaveSignCallsInChecks() {
|
||||
String arenaId = "castle";
|
||||
ArenaSign sign = new ArenaSign(null, "", arenaId, "leave");
|
||||
Player player = mock(Player.class);
|
||||
Arena arena = mock(Arena.class);
|
||||
when(arenaMaster.getArenaWithName(arenaId))
|
||||
.thenReturn(arena);
|
||||
|
||||
subject.invoke(sign, player);
|
||||
|
||||
verify(arena).inArena(player);
|
||||
verify(arena).inLobby(player);
|
||||
verify(arena).inSpec(player);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void leaveSignCallsPlayerLeave() {
|
||||
String arenaId = "castle";
|
||||
ArenaSign sign = new ArenaSign(null, "", arenaId, "leave");
|
||||
Player player = mock(Player.class);
|
||||
Arena arena = mock(Arena.class);
|
||||
when(arena.inArena(player)).thenReturn(true);
|
||||
when(arenaMaster.getArenaWithName(arenaId))
|
||||
.thenReturn(arena);
|
||||
|
||||
subject.invoke(sign, player);
|
||||
|
||||
verify(arena).playerLeave(player);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentArenaReportsToPlayer() {
|
||||
String arenaId = "castle";
|
||||
ArenaSign sign = new ArenaSign(null, "", arenaId, "join");
|
||||
Player player = mock(Player.class);
|
||||
when(arenaMaster.getArenaWithName(arenaId))
|
||||
.thenReturn(null);
|
||||
|
||||
subject.invoke(sign, player);
|
||||
|
||||
verify(messenger).tell(eq(player), anyString());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import org.bukkit.Location;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@RunWith(MockitoJUnitRunner.StrictStubs.class)
|
||||
public class RedrawsArenaSignsTest {
|
||||
|
||||
SignStore signStore;
|
||||
TemplateStore templateStore;
|
||||
RendersTemplate rendersTemplate;
|
||||
SetsLines setsSignLines;
|
||||
|
||||
RedrawsArenaSigns subject;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
signStore = mock(SignStore.class);
|
||||
when(signStore.findByArenaId(any()))
|
||||
.thenReturn(Collections.emptyList());
|
||||
|
||||
templateStore = mock(TemplateStore.class);
|
||||
when(templateStore.findById(any()))
|
||||
.thenReturn(Optional.empty());
|
||||
|
||||
rendersTemplate = mock(RendersTemplate.class);
|
||||
when(rendersTemplate.render(any(), any()))
|
||||
.thenReturn(new String[]{"a", "b", "c", "d"});
|
||||
|
||||
setsSignLines = mock(SetsLines.class);
|
||||
|
||||
subject = new RedrawsArenaSigns(
|
||||
signStore,
|
||||
templateStore,
|
||||
rendersTemplate,
|
||||
setsSignLines
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noSignsMeansNoRenderingOrLineSetting() {
|
||||
Arena arena = arena("castle");
|
||||
|
||||
subject.redraw(arena);
|
||||
|
||||
verifyZeroInteractions(rendersTemplate);
|
||||
verifyZeroInteractions(setsSignLines);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void renderFoundTemplate() {
|
||||
String arenaId = "castle";
|
||||
Arena arena = arena(arenaId);
|
||||
ArenaSign sign = sign("join", arenaId);
|
||||
when(signStore.findByArenaId(arenaId))
|
||||
.thenReturn(Collections.singletonList(sign));
|
||||
Template template = template("template", "some", "info", "about", "arena");
|
||||
when(templateStore.findById(sign.templateId))
|
||||
.thenReturn(Optional.of(template));
|
||||
|
||||
subject.redraw(arena);
|
||||
|
||||
verify(rendersTemplate).render(template, arena);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setRenderedTemplateOnSign() {
|
||||
String arenaId = "castle";
|
||||
Arena arena = arena(arenaId);
|
||||
ArenaSign sign = sign("join", arenaId);
|
||||
when(signStore.findByArenaId(sign.arenaId))
|
||||
.thenReturn(Collections.singletonList(sign));
|
||||
Template template = template("template", "try", "with", "more", "fireballs");
|
||||
when(templateStore.findById(sign.templateId))
|
||||
.thenReturn(Optional.of(template));
|
||||
String[] lines = new String[]{"this", "is", "a", "sign"};
|
||||
when(rendersTemplate.render(template, arena))
|
||||
.thenReturn(lines);
|
||||
|
||||
subject.redraw(arena);
|
||||
|
||||
verify(setsSignLines).set(sign.location, lines);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void renderEachTemplateOnlyOnce() {
|
||||
String arenaId = "castle";
|
||||
Arena arena = arena(arenaId);
|
||||
String templateId1 = "join";
|
||||
String templateId2 = "info";
|
||||
List<ArenaSign> signs = new ArrayList<>();
|
||||
signs.add(sign(templateId1, arenaId));
|
||||
signs.add(sign(templateId1, arenaId));
|
||||
signs.add(sign(templateId1, arenaId));
|
||||
signs.add(sign(templateId2, arenaId));
|
||||
when(signStore.findByArenaId(arenaId))
|
||||
.thenReturn(signs);
|
||||
Template template1 = template(templateId1, "join", "a", "MobArena", "today!");
|
||||
Template template2 = template(templateId2, "join", "another", "MobArena", "tomorrow!");
|
||||
when(templateStore.findById(templateId1))
|
||||
.thenReturn(Optional.of(template1));
|
||||
when(templateStore.findById(templateId2))
|
||||
.thenReturn(Optional.of(template2));
|
||||
|
||||
subject.redraw(arena);
|
||||
|
||||
verify(rendersTemplate, times(1)).render(template1, arena);
|
||||
verify(rendersTemplate, times(1)).render(template2, arena);
|
||||
verify(setsSignLines, times(signs.size())).set(any(), any());
|
||||
}
|
||||
|
||||
private Arena arena(String arenaId) {
|
||||
Arena arena = mock(Arena.class);
|
||||
when(arena.configName()).thenReturn(arenaId);
|
||||
return arena;
|
||||
}
|
||||
|
||||
private ArenaSign sign(String templateId, String arenaId) {
|
||||
Location location = mock(Location.class);
|
||||
return new ArenaSign(location, templateId, arenaId, "join");
|
||||
}
|
||||
|
||||
private Template template(String id, String l1, String l2, String l3, String l4) {
|
||||
return new Template.Builder(id)
|
||||
.withBase(new String[]{l1, l2, l3, l4})
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@RunWith(MockitoJUnitRunner.StrictStubs.class)
|
||||
public class RemovesSignAtLocationTest {
|
||||
|
||||
SignStore signStore;
|
||||
SavesSignStore savesSignStore;
|
||||
|
||||
RemovesSignAtLocation subject;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
signStore = mock(SignStore.class);
|
||||
savesSignStore = mock(SavesSignStore.class);
|
||||
|
||||
subject = new RemovesSignAtLocation(
|
||||
signStore,
|
||||
savesSignStore
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noSignMeansNoWrite() {
|
||||
Location location = mock(Location.class);
|
||||
when(signStore.remove(location))
|
||||
.thenReturn(Optional.empty());
|
||||
|
||||
subject.remove(location);
|
||||
|
||||
verifyZeroInteractions(savesSignStore);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void signRemovedWritesStore() {
|
||||
Location location = mock(Location.class);
|
||||
ArenaSign sign = new ArenaSign(location, "", "", "");
|
||||
when(signStore.remove(location))
|
||||
.thenReturn(Optional.of(sign));
|
||||
|
||||
subject.remove(location);
|
||||
|
||||
verify(savesSignStore).save(signStore);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.waves.WaveManager;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@RunWith(MockitoJUnitRunner.StrictStubs.class)
|
||||
public class RendersTemplateTest {
|
||||
|
||||
RendersTemplate subject;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
subject = new RendersTemplate();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rendersArenaName() {
|
||||
String name = "castle";
|
||||
Arena arena = arena(name, false, false);
|
||||
Template template = new Template.Builder("template")
|
||||
.withBase(new String[]{"<arena-name>", "", "", ""})
|
||||
.build();
|
||||
|
||||
String[] result = subject.render(template, arena);
|
||||
|
||||
String[] expected = new String[]{name, "", "", ""};
|
||||
assertThat(result, equalTo(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultsToBaseIfArenaIsNotRunning() {
|
||||
Arena arena = arena("castle", false, false);
|
||||
String[] base = {"this", "is", "the", "base"};
|
||||
Template template = new Template.Builder("template")
|
||||
.withBase(base)
|
||||
.withRunning(new String[]{"here", "is", "running", "yo"})
|
||||
.build();
|
||||
|
||||
String[] result = subject.render(template, arena);
|
||||
|
||||
assertThat(result, equalTo(base));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void idleOverridesBaseIfNotRunning() {
|
||||
Arena arena = arena("castle", false, false);
|
||||
String[] idle = {"relax", "don't", "do", "it"};
|
||||
Template template = new Template.Builder("template")
|
||||
.withBase(new String[]{"this", "is", "the", "base"})
|
||||
.withIdle(idle)
|
||||
.build();
|
||||
|
||||
String[] result = subject.render(template, arena);
|
||||
|
||||
assertThat(result, equalTo(idle));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runningOverridesBaseIfArenaIsRunning() {
|
||||
Arena arena = arena("castle", true, false);
|
||||
String[] running = {"here", "is", "running", "yo"};
|
||||
Template template = new Template.Builder("template")
|
||||
.withBase(new String[]{"this", "is", "the", "base"})
|
||||
.withRunning(running)
|
||||
.build();
|
||||
|
||||
String[] result = subject.render(template, arena);
|
||||
|
||||
assertThat(result, equalTo(running));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lobbyOverridesBaseIfPlayersInLobby() {
|
||||
Arena arena = arena("castle", false, true);
|
||||
String[] joining = {"we", "in", "da", "lobby"};
|
||||
Template template = new Template.Builder("template")
|
||||
.withBase(new String[]{"this", "is", "the", "base"})
|
||||
.withJoining(joining)
|
||||
.build();
|
||||
|
||||
String[] result = subject.render(template, arena);
|
||||
|
||||
assertThat(result, equalTo(joining));
|
||||
}
|
||||
|
||||
private Arena arena(String name, boolean running, boolean lobby) {
|
||||
Arena arena = mock(Arena.class);
|
||||
when(arena.configName()).thenReturn(name);
|
||||
when(arena.isRunning()).thenReturn(running);
|
||||
when(arena.getPlayersInLobby()).thenReturn(lobby ? Collections.singleton(null) : Collections.emptySet());
|
||||
when(arena.getWaveManager()).thenReturn(mock(WaveManager.class));
|
||||
return arena;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
package com.garbagemule.MobArena.signs;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import org.bukkit.Location;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@RunWith(MockitoJUnitRunner.StrictStubs.class)
|
||||
public class StoresNewSignTest {
|
||||
|
||||
ArenaMaster arenaMaster;
|
||||
TemplateStore templateStore;
|
||||
SignStore signStore;
|
||||
SavesSignStore savesSignStore;
|
||||
|
||||
StoresNewSign subject;
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
arenaMaster = mock(ArenaMaster.class);
|
||||
when(arenaMaster.getArenaWithName(any()))
|
||||
.thenReturn(null);
|
||||
|
||||
templateStore = mock(TemplateStore.class);
|
||||
when(templateStore.findById(any()))
|
||||
.thenReturn(Optional.empty());
|
||||
|
||||
signStore = mock(SignStore.class);
|
||||
|
||||
savesSignStore = mock(SavesSignStore.class);
|
||||
|
||||
subject = new StoresNewSign(
|
||||
arenaMaster,
|
||||
templateStore,
|
||||
signStore,
|
||||
savesSignStore
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void throwOnNonExistentArena() {
|
||||
Location location = mock(Location.class);
|
||||
String arenaId = "castle";
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
|
||||
subject.store(location, arenaId, "", "");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void throwOnNonExistentTemplate() {
|
||||
Location location = mock(Location.class);
|
||||
String arenaId = "castle";
|
||||
Arena arena = mock(Arena.class);
|
||||
when(arenaMaster.getArenaWithName(arenaId))
|
||||
.thenReturn(arena);
|
||||
String templateId = "template";
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
|
||||
subject.store(location, arenaId, templateId, "");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void throwOnNonInvalidSignType() {
|
||||
Location location = mock(Location.class);
|
||||
String arenaId = "castle";
|
||||
Arena arena = mock(Arena.class);
|
||||
when(arenaMaster.getArenaWithName(arenaId))
|
||||
.thenReturn(arena);
|
||||
String templateId = "a very nice template";
|
||||
Template template = template(templateId);
|
||||
when(templateStore.findById(templateId))
|
||||
.thenReturn(Optional.of(template));
|
||||
String signType = "not a real sign type";
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
|
||||
subject.store(location, arenaId, templateId, signType);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void storesSignAndWritesToDisk() {
|
||||
Location location = mock(Location.class);
|
||||
String arenaId = "castle";
|
||||
Arena arena = mock(Arena.class);
|
||||
when(arenaMaster.getArenaWithName(arenaId))
|
||||
.thenReturn(arena);
|
||||
String templateId = "a very nice template";
|
||||
Template template = template(templateId);
|
||||
when(templateStore.findById(templateId))
|
||||
.thenReturn(Optional.of(template));
|
||||
String signType = "join";
|
||||
|
||||
subject.store(location, arenaId, templateId, signType);
|
||||
|
||||
ArgumentCaptor<ArenaSign> captor = ArgumentCaptor.forClass(ArenaSign.class);
|
||||
verify(signStore).store(captor.capture());
|
||||
verify(savesSignStore).save(signStore);
|
||||
ArenaSign sign = captor.getValue();
|
||||
assertThat(sign.location, equalTo(location));
|
||||
assertThat(sign.arenaId, equalTo(arenaId));
|
||||
assertThat(sign.templateId, equalTo(templateId));
|
||||
assertThat(sign.type, equalTo(signType));
|
||||
}
|
||||
|
||||
private Template template(String id) {
|
||||
return new Template.Builder(id)
|
||||
.withBase(new String[]{"", "", "", ""})
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user