Add dynamic rotations (#2)

* Start work on multidynamic rotations

* Finish up dynamic rotations ♻️

* Fix typo

* Some changes to Dynamic Rotations

* Add dynamic player count requirements to config.yml

* Fix messages and change participating players count logic
This commit is contained in:
Javi 2017-03-25 20:39:52 +01:00 committed by GitHub
parent b883ef5799
commit 7e5325daaf
9 changed files with 100 additions and 4 deletions

View File

@ -65,6 +65,9 @@ map.gamemode.long.mixed = Mixed
map.gamemode.long.skywars = Skywars
map.gamemode.long.survival = Survival Games
rotation.change.broadcast.title = Changing Rotation...
rotation.change.broadcast.info = The server is automatically changing rotations to best accommodate the current player count.
command.match.matchInfo.title = Match
command.match.matchInfo.title.tip = View this match on the web
command.match.matchInfo.time = Time

View File

@ -40,6 +40,7 @@ import tc.oc.pgm.match.MatchManager;
import tc.oc.pgm.match.MatchPlayer;
import tc.oc.pgm.polls.PollListener;
import tc.oc.pgm.polls.PollManager;
import tc.oc.pgm.rotation.DynamicRotationChangeListener;
import tc.oc.pgm.start.StartCommands;
import tc.oc.pgm.tablist.MatchTabManager;
import tc.oc.pgm.timelimit.TimeLimitCommands;
@ -199,6 +200,7 @@ public final class PGM extends JavaPlugin {
this.registerEvents(new CraftingProtect());
this.registerEvents(new ObjectivesFireworkListener());
this.registerEvents(new ItemTransferListener());
this.registerEvents(new DynamicRotationChangeListener());
}
public void registerEvents(Listener listener) {

View File

@ -130,4 +130,11 @@ public class MapModuleContext extends ModuleContext<MapModule, MapScoped> {
public Range<Integer> playerLimits() {
return playerLimits.get();
}
public Integer playerLimitAverage() {
Range<Integer> lims = playerLimits();
int sum = lims.lowerEndpoint() + lims.upperEndpoint();
return ((Double) Math.floor(sum/2)).intValue();
}
}

View File

@ -0,0 +1,61 @@
package tc.oc.pgm.rotation;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.TranslatableComponent;
import org.bukkit.configuration.Configuration;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import tc.oc.commons.core.chat.Component;
import tc.oc.pgm.Config;
import tc.oc.pgm.PGM;
import tc.oc.pgm.cycle.CycleMatchModule;
import tc.oc.pgm.events.MatchEndEvent;
public class DynamicRotationChangeListener implements Listener {
public static void main(String[] args) {
System.out.println(RotationCategory.MEDIUM.toString().toLowerCase());
}
@EventHandler
public void onMatchEnd(MatchEndEvent event) {
RotationManager rotationManager = PGM.getMatchManager().getRotationManager();
// Ignore if there is only one rotation available
if (rotationManager.getRotations().size() == 1) return;
// Number of players we can assume is active
int participatingPlayers = event.getMatch().getServer().getOnlinePlayers().size();
RotationCategory appr = getAppropriateRotationCategory(participatingPlayers, rotationManager);
if (appr != null && rotationManager.getRotation(appr.toString().toLowerCase()) != rotationManager.getRotation()) {
rotationManager.setRotation(rotationManager.getRotation(appr.toString().toLowerCase()));
CycleMatchModule cmm = event.getMatch().needMatchModule(CycleMatchModule.class);
cmm.startCountdown(cmm.getConfig().countdown());
event.getMatch().sendMessage(new TextComponent(ChatColor.RED + "" + ChatColor.STRIKETHROUGH + "---------------------------------------------------"));
event.getMatch().sendMessage(new Component(new TranslatableComponent("rotation.change.broadcast.title"), ChatColor.GOLD));
event.getMatch().sendMessage(new Component(new TranslatableComponent("rotation.change.broadcast.info"), ChatColor.YELLOW));
event.getMatch().sendMessage(new TextComponent(ChatColor.RED + "" + ChatColor.STRIKETHROUGH + "---------------------------------------------------"));
}
}
/**
* Returns appropriate rotation looking at how many players (participating) are online.
*
* @param players Current participant player count.
* @param rotationManager The {@link RotationManager}
* @return any of {@link RotationCategory}
*/
private RotationCategory getAppropriateRotationCategory(int players, RotationManager rotationManager) {
Configuration config = Config.getConfiguration();
int medium = config.getInt("rotation.providers.file.medium.count");
int mega = config.getInt("rotation.providers.file.mega.count");
if (players > medium && players <= mega && rotationManager.getRotation("medium") != null) return RotationCategory.MEDIUM;
if (players > mega && rotationManager.getRotation("mega") != null) return RotationCategory.MEGA;
return RotationCategory.MINI;
}
}

View File

@ -34,9 +34,10 @@ public class FileRotationProviderFactory {
if(!rotationFile.isAbsolute()) rotationFile = dataPath.resolve(rotationFile);
int priority = provider.getInt("priority", 0);
int count = provider.getInt("count", 0);
if(Files.isRegularFile(rotationFile)) {
providers.add(new RotationProviderInfo(new FileRotationProvider(mapLibrary, name, rotationFile, dataPath), name, priority));
providers.add(new RotationProviderInfo(new FileRotationProvider(mapLibrary, name, rotationFile, dataPath), name, priority, count));
} else if(minecraftService.getLocalServer().startup_visibility() == ServerDoc.Visibility.PUBLIC) {
// This is not a perfect way to decide whether or not to throw an error, but it's the best we can do right now
mapLibrary.getLogger().severe("Missing rotation file: " + rotationFile);

View File

@ -0,0 +1,5 @@
package tc.oc.pgm.rotation;
public enum RotationCategory {
MINI, MEDIUM, MEGA
}

View File

@ -116,12 +116,12 @@ public class RotationManager {
return null;
}
public void addProvider(@Nonnull RotationProvider provider, @Nonnull String name, int priority) {
public void addProvider(@Nonnull RotationProvider provider, @Nonnull String name, int priority, int count) {
Preconditions.checkNotNull(provider, "rotation provider");
Preconditions.checkNotNull(name, "name");
Preconditions.checkArgument(this.getProviderByName(name) == null, "provider is already registered to name");
RotationProviderInfo state = new RotationProviderInfo(provider, name, priority);
RotationProviderInfo state = new RotationProviderInfo(provider, name, priority, count);
this.providers.add(state);
}

View File

@ -8,15 +8,17 @@ public class RotationProviderInfo implements Comparable<RotationProviderInfo> {
public final @Nonnull
RotationProvider provider;
public final int priority;
public final int count;
public final @Nonnull String name;
public RotationProviderInfo(@Nonnull RotationProvider provider, @Nonnull String name, int priority) {
public RotationProviderInfo(@Nonnull RotationProvider provider, @Nonnull String name, int priority, int count) {
Preconditions.checkNotNull(provider, "rotation provider");
Preconditions.checkNotNull(name, "name");
this.provider = provider;
this.name = name;
this.priority = priority;
this.count = count;
}
@Override

View File

@ -1,5 +1,6 @@
package tc.oc.pgm.rotation;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
@ -39,6 +40,20 @@ public final class RotationState {
return this.maps;
}
/**
* Gets the approximate number of players supposed to be playing the rotation maps.
* @return Integer with average size of teams over all maps
*/
public @Nonnull Integer getAverageNeededPlayers() {
List<Integer> players = new ArrayList<>();
int total = 0;
getMaps().stream().forEach(m -> players.add(m.getContext().playerLimitAverage()));
for (int pl : players) { total += pl; }
return ((Double) Math.floor(total / players.size())).intValue();
}
/**
* Gets the next map in the rotation as specified by the next id.
* @return Next map in rotation