Custom map providers / Added next map specification command

This commit is contained in:
Anuken 2019-11-18 18:56:49 -05:00
parent ad25cd8074
commit 134fea445c
2 changed files with 129 additions and 59 deletions

View File

@ -8,10 +8,12 @@ import io.anuke.arc.collection.IntSet.*;
import io.anuke.arc.files.*;
import io.anuke.arc.func.*;
import io.anuke.arc.graphics.*;
import io.anuke.arc.util.ArcAnnotate.*;
import io.anuke.arc.util.*;
import io.anuke.arc.util.async.*;
import io.anuke.arc.util.io.*;
import io.anuke.arc.util.serialization.*;
import io.anuke.mindustry.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.ctype.*;
import io.anuke.mindustry.game.EventType.*;
@ -34,9 +36,30 @@ public class Maps{
/** Serializer for meta. */
private Json json = new Json();
private ShuffleMode shuffleMode = ShuffleMode.all;
private @Nullable MapProvider shuffler;
private AsyncExecutor executor = new AsyncExecutor(2);
private ObjectSet<Map> previewList = new ObjectSet<>();
public ShuffleMode getShuffleMode(){
return shuffleMode;
}
public void setShuffleMode(ShuffleMode mode){
this.shuffleMode = mode;
}
/** Set the provider for the map(s) to be played on. Will override the default shuffle mode setting.*/
public void setMapProvider(MapProvider provider){
this.shuffler = provider;
}
/** @return the next map to shuffle to. May be null, in which case the server should be stopped. */
public @Nullable Map getNextMap(@Nullable Map previous){
return shuffler != null ? shuffler.next(previous) : shuffleMode.next(previous);
}
/** Returns a list of all maps, including custom ones. */
public Array<Map> all(){
return maps;
@ -422,4 +445,37 @@ public class Maps{
return map;
}
public interface MapProvider{
@Nullable Map next(@Nullable Map previous);
}
public enum ShuffleMode implements MapProvider{
none(map -> null),
all(prev -> {
Array<Map> maps = Array.withArrays(Vars.maps.defaultMaps(), Vars.maps.customMaps());
maps.shuffle();
return maps.find(m -> m != prev || maps.size == 1);
}),
custom(prev -> {
Array<Map> maps = Array.withArrays(Vars.maps.customMaps());
maps.shuffle();
return maps.find(m -> m != prev || maps.size == 1);
}),
builtin(prev -> {
Array<Map> maps = Array.withArrays(Vars.maps.defaultMaps());
maps.shuffle();
return maps.find(m -> m != prev || maps.size == 1);
});
private final MapProvider provider;
ShuffleMode(MapProvider provider){
this.provider = provider;
}
@Override
public Map next(@Nullable Map previous){
return provider.next(previous);
}
}
}

View File

@ -5,6 +5,7 @@ import io.anuke.arc.collection.*;
import io.anuke.arc.collection.Array.*;
import io.anuke.arc.files.*;
import io.anuke.arc.util.*;
import io.anuke.arc.util.ArcAnnotate.*;
import io.anuke.arc.util.Timer;
import io.anuke.arc.util.CommandHandler.*;
import io.anuke.arc.util.Timer.*;
@ -21,6 +22,7 @@ import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.io.*;
import io.anuke.mindustry.maps.Map;
import io.anuke.mindustry.maps.*;
import io.anuke.mindustry.maps.Maps.*;
import io.anuke.mindustry.mod.Mods.*;
import io.anuke.mindustry.net.Administration.*;
import io.anuke.mindustry.net.Packets.*;
@ -48,6 +50,7 @@ public class ServerControl implements ApplicationListener{
private boolean inExtraRound;
private Task lastTask;
private Gamemode lastMode = Gamemode.survival;
private @Nullable Map nextMapOverride;
private Thread socketThread;
private PrintWriter socketOutput;
@ -57,7 +60,7 @@ public class ServerControl implements ApplicationListener{
"shufflemode", "normal",
"bans", "",
"admins", "",
"shuffle", true,
"shufflemode", "all",
"crashreport", false,
"port", port,
"logging", true,
@ -142,34 +145,34 @@ public class ServerControl implements ApplicationListener{
warn("&lyIt is highly advised to specify which version you're using by building with gradle args &lc-Pbuildversion=&lm<build>&ly.");
}
//set up default shuffle mode
try{
maps.setShuffleMode(ShuffleMode.valueOf(Core.settings.getString("shufflemode")));
}catch(Exception e){
maps.setShuffleMode(ShuffleMode.all);
}
Events.on(GameOverEvent.class, event -> {
if(inExtraRound) return;
info("Game over!");
displayStatus();
if(state.rules.waves){
info("&lcGame over! Reached wave &ly{0}&lc with &ly{1}&lc players online on map &ly{2}&lc.", state.wave, playerGroup.size(), Strings.capitalize(world.getMap().name()));
}else{
info("&lcGame over! Team &ly{0}&lc is victorious with &ly{1}&lc players online on map &ly{2}&lc.", event.winner.name(), playerGroup.size(), Strings.capitalize(world.getMap().name()));
}
if(Core.settings.getBool("shuffle")){
if(maps.all().size > 0){
Array<Map> maps = Array.with(Vars.maps.customMaps().size == 0 ? Vars.maps.defaultMaps() : Vars.maps.customMaps());
maps.shuffle();
//set next map to be played
Map map = nextMapOverride != null ? nextMapOverride : maps.getNextMap(world.getMap());
nextMapOverride = null;
if(map != null){
Call.onInfoMessage((state.rules.pvp
? "[YELLOW]The " + event.winner.name() + " team is victorious![]" : "[SCARLET]Game over![]")
+ "\nNext selected map:[accent] " + map.name() + "[]"
+ (map.tags.containsKey("author") && !map.tags.get("author").trim().isEmpty() ? " by[accent] " + map.author() + "[]" : "") + "." +
"\nNew game begins in " + roundExtraTime + "[] seconds.");
Map previous = world.getMap();
Map map = maps.find(m -> m != previous || maps.size == 1);
info("Selected next map to be {0}.", map.name());
if(map != null){
Call.onInfoMessage((state.rules.pvp
? "[YELLOW]The " + event.winner.name() + " team is victorious![]" : "[SCARLET]Game over![]")
+ "\nNext selected map:[accent] " + map.name() + "[]"
+ (map.tags.containsKey("author") && !map.tags.get("author").trim().isEmpty() ? " by[accent] " + map.author() + "[]" : "") + "." +
"\nNew game begins in " + roundExtraTime + "[] seconds.");
info("Selected next map to be {0}.", map.name());
play(true, () -> world.loadMap(map, map.applyRules(lastMode)));
}else{
Log.err("No suitable map found.");
}
}
play(true, () -> world.loadMap(map, map.applyRules(lastMode)));
}else{
netServer.kickAll(KickReason.gameover);
state.set(State.menu);
@ -304,7 +307,29 @@ public class ServerControl implements ApplicationListener{
});
handler.register("status", "Display server status.", arg -> {
displayStatus();
if(state.is(State.menu)){
info("Status: &rserver closed");
}else{
info("Status:");
info(" &lyPlaying on map &fi{0}&fb &lb/&ly Wave {1}", Strings.capitalize(world.getMap().name()), state.wave);
if(state.rules.waves){
info("&ly {0} enemies.", unitGroups[Team.crux.ordinal()].size());
}else{
info("&ly {0} seconds until next wave.", (int)(state.wavetime / 60));
}
info(" &ly{0} FPS, {1} MB used.", (int)(60f / Time.delta()), Core.app.getJavaHeap() / 1024 / 1024);
if(playerGroup.size() > 0){
info(" &lyPlayers: {0}", playerGroup.size());
for(Player p : playerGroup.all()){
info(" &y{0} / {1}", p.name, p.uuid);
}
}else{
info(" &lyNo players connected.");
}
}
});
handler.register("mods", "Display all loaded mods.", arg -> {
@ -553,14 +578,29 @@ public class ServerControl implements ApplicationListener{
}
});
handler.register("shuffle", "<on/off>", "Set map shuffling.", arg -> {
if(!arg[0].equals("on") && !arg[0].equals("off")){
err("Invalid shuffle mode.");
return;
handler.register("shuffle", "[none/all/custom/builtin]", "Set map shuffling mode.", arg -> {
if(arg.length == 0){
info("Shuffle mode current set to &ly'{0}'&lg.", maps.getShuffleMode());
}else{
try{
ShuffleMode mode = ShuffleMode.valueOf(arg[0]);
Core.settings.putSave("shufflemode", mode.name());
maps.setShuffleMode(mode);
info("Shuffle mode set to &ly'{0}'&lg.", arg[0]);
}catch(Exception e){
err("Invalid shuffle mode.");
}
}
});
handler.register("nextmap", "<mapname...>", "Set the next map to be played after a game-over. Overrides shuffling.", arg -> {
Map res = maps.all().find(map -> map.name().equalsIgnoreCase(arg[0].replace('_', ' ')) || map.name().equalsIgnoreCase(arg[0]));
if(res != null){
nextMapOverride = res;
Log.info("Next map set to &ly'{0}'.", res.name());
}else{
Log.err("No map '{0}' found.", arg[0]);
}
Core.settings.put("shuffle", arg[0].equals("on"));
Core.settings.save();
info("Shuffle mode set to '{0}'.", arg[0]);
});
handler.register("kick", "<username...>", "Kick a person by name.", arg -> {
@ -759,7 +799,7 @@ public class ServerControl implements ApplicationListener{
handler.register("gameover", "Force a game over.", arg -> {
if(state.is(State.menu)){
info("Not playing a map.");
err("Not playing a map.");
return;
}
@ -809,32 +849,6 @@ public class ServerControl implements ApplicationListener{
}
}
private void displayStatus() {
if(state.is(State.menu)){
info("Status: &rserver closed");
}else{
info("Status:");
info(" &lyPlaying on map &fi{0}&fb &lb/&ly Wave {1}", Strings.capitalize(world.getMap().name()), state.wave);
if(state.rules.waves){
info("&ly {0} enemies.", unitGroups[Team.crux.ordinal()].size());
}else{
info("&ly {0} seconds until next wave.", (int)(state.wavetime / 60));
}
info(" &ly{0} FPS, {1} MB used.", (int)(60f / Time.delta()), Core.app.getJavaHeap() / 1024 / 1024);
if(playerGroup.size() > 0){
info(" &lyPlayers: {0}", playerGroup.size());
for(Player p : playerGroup.all()){
info(" &y{0} / {1}", p.name, p.uuid);
}
}else{
info(" &lyNo players connected.");
}
}
}
private void readCommands(){
Scanner scan = new Scanner(System.in);