Store rotation state in the database
This commit is contained in:
parent
55aacbddb1
commit
0caea52598
|
@ -106,7 +106,7 @@ public interface ServerDoc {
|
|||
* Startup info received from the API
|
||||
*/
|
||||
@Serialize
|
||||
interface Configuration extends Partial {
|
||||
interface Configuration extends Rotations {
|
||||
String settings_profile();
|
||||
Map<UUID, String> operators();
|
||||
@Nullable Team team();
|
||||
|
@ -117,7 +117,6 @@ public interface ServerDoc {
|
|||
Visibility startup_visibility();
|
||||
boolean whitelist_enabled();
|
||||
boolean waiting_room();
|
||||
|
||||
@Nullable String resource_pack_url();
|
||||
@Nullable String resource_pack_sha1();
|
||||
boolean resource_pack_fast_update();
|
||||
|
@ -142,6 +141,17 @@ public interface ServerDoc {
|
|||
Set<String> queued_mutations();
|
||||
}
|
||||
|
||||
@Serialize
|
||||
interface Rotations extends Partial {
|
||||
List<Rotation> rotations();
|
||||
}
|
||||
|
||||
@Serialize
|
||||
interface Rotation extends Document {
|
||||
String name();
|
||||
String next_map_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Status sent to the API from Lobby
|
||||
*/
|
||||
|
|
|
@ -282,4 +282,9 @@ public class LocalServerDocument extends StartupServerDocument implements Server
|
|||
public Set<String> queued_mutations() {
|
||||
return mutations != null ? mutations.queued_mutations() : Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServerDoc.Rotation> rotations() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -209,7 +209,13 @@ public class MapCommands {
|
|||
final RotationState rotation = CommandUtils.getRotation(args.getFlag('n'), sender);
|
||||
int page = args.getInteger(0, 1);
|
||||
|
||||
new PrettyPaginatedResult<PGMMap>(PGMTranslations.get().t("command.map.currentRotation.title", sender) + "(" + ChatColor.DARK_AQUA + PGM.getMatchManager().getRotationManager().getCurrentRotationName() + ChatColor.RESET + ")") {
|
||||
String header = PGMTranslations.get().t("command.map.currentRotation.title", sender);
|
||||
String name = PGM.getMatchManager().getRotationManager().getCurrentRotationName();
|
||||
if(!name.equalsIgnoreCase("default")) {
|
||||
header += " (" + ChatColor.DARK_AQUA + name + ChatColor.RESET + ")";
|
||||
}
|
||||
|
||||
new PrettyPaginatedResult<PGMMap>(header) {
|
||||
@Override public String format(PGMMap map, int index) {
|
||||
ChatColor color = index == rotation.getNextId() ? ChatColor.DARK_AQUA : ChatColor.WHITE;
|
||||
return color.toString() + (index + 1) + ". " + map.getInfo().getShortDescription(sender);
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.bukkit.ChatColor;
|
|||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.Configuration;
|
||||
import org.bukkit.event.EventBus;
|
||||
import tc.oc.api.minecraft.MinecraftService;
|
||||
import tc.oc.api.util.Permissions;
|
||||
import tc.oc.commons.core.logging.Loggers;
|
||||
import tc.oc.pgm.PGM;
|
||||
|
@ -48,6 +49,7 @@ public class MatchManager implements MatchFinder {
|
|||
private final FileRotationProviderFactory fileRotationProviderFactory;
|
||||
private final EventBus eventBus;
|
||||
private final MatchLoader matchLoader;
|
||||
private final MinecraftService minecraftService;
|
||||
private @Nullable RotationManager rotationManager;
|
||||
|
||||
/** Custom set next map. */
|
||||
|
@ -64,7 +66,8 @@ public class MatchManager implements MatchFinder {
|
|||
MapErrorTracker mapErrorTracker,
|
||||
FileRotationProviderFactory fileRotationProviderFactory,
|
||||
EventBus eventBus,
|
||||
MatchLoader matchLoader) throws MapNotFoundException {
|
||||
MatchLoader matchLoader,
|
||||
MinecraftService minecraftService) throws MapNotFoundException {
|
||||
|
||||
this.pluginDataFolder = pluginDataFolder;
|
||||
this.mapErrorTracker = mapErrorTracker;
|
||||
|
@ -75,6 +78,7 @@ public class MatchManager implements MatchFinder {
|
|||
this.mapLoader = mapLoader;
|
||||
this.eventBus = eventBus;
|
||||
this.matchLoader = matchLoader;
|
||||
this.minecraftService = minecraftService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -126,6 +130,7 @@ public class MatchManager implements MatchFinder {
|
|||
if(rotationManager == null) {
|
||||
rotationManager = new RotationManager(
|
||||
log,
|
||||
minecraftService,
|
||||
config.get(),
|
||||
mapLibrary.getMaps().iterator().next(),
|
||||
fileRotationProviderFactory.parse(
|
||||
|
|
|
@ -16,6 +16,8 @@ import com.google.common.base.Charsets;
|
|||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.time.Instant;
|
||||
|
||||
import tc.oc.api.docs.virtual.ServerDoc;
|
||||
import tc.oc.commons.core.logging.ClassLogger;
|
||||
import tc.oc.commons.core.util.Joiners;
|
||||
import tc.oc.pgm.PGM;
|
||||
|
@ -32,8 +34,9 @@ public class FileRotationProvider extends AbstractRotationProvider {
|
|||
private final String name;
|
||||
private final Path rotationFile;
|
||||
private final Path dataPath;
|
||||
private final Optional<ServerDoc.Rotation> rotationApi;
|
||||
|
||||
public FileRotationProvider(MapLibrary mapLibrary, String name, Path rotationFile, Path dataPath) {
|
||||
public FileRotationProvider(MapLibrary mapLibrary, String name, Path rotationFile, Path dataPath, Optional<ServerDoc.Rotation> rotationApi) {
|
||||
Preconditions.checkNotNull(mapLibrary, "map manager");
|
||||
Preconditions.checkNotNull(rotationFile, "rotation path");
|
||||
Preconditions.checkNotNull(dataPath, "data path");
|
||||
|
@ -46,6 +49,7 @@ public class FileRotationProvider extends AbstractRotationProvider {
|
|||
this.name = name;
|
||||
this.rotationFile = rotationFile;
|
||||
this.dataPath = dataPath;
|
||||
this.rotationApi = rotationApi;
|
||||
}
|
||||
|
||||
Path nextIdFile() {
|
||||
|
@ -54,7 +58,7 @@ public class FileRotationProvider extends AbstractRotationProvider {
|
|||
|
||||
@Override
|
||||
public @Nonnull Future<?> loadRotations() {
|
||||
return getExecutorService().submit((Runnable) () -> {
|
||||
return getExecutorService().submit(() -> {
|
||||
try {
|
||||
setRotation(name, loadRotationFromDisk(), Instant.now());
|
||||
} catch(IOException e) {
|
||||
|
@ -64,8 +68,8 @@ public class FileRotationProvider extends AbstractRotationProvider {
|
|||
}
|
||||
|
||||
private RotationState loadRotationFromDisk() throws IOException {
|
||||
int nextId = this.parseNextId();
|
||||
List<PGMMap> maps = this.parseRotationNames();
|
||||
int nextId = this.parseNextId(maps);
|
||||
|
||||
if(maps.isEmpty()) {
|
||||
throw new IOException(String.format("Rotation '%s' was empty!", name));
|
||||
|
@ -80,13 +84,17 @@ public class FileRotationProvider extends AbstractRotationProvider {
|
|||
return new RotationState(maps, nextId);
|
||||
}
|
||||
|
||||
private int parseNextId() {
|
||||
private int parseNextId(List<PGMMap> maps) {
|
||||
List<String> lines;
|
||||
try {
|
||||
lines = Files.readAllLines(nextIdFile(), Charsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
this.logger.warning("Failed to read next id from " + nextIdFile().toString());
|
||||
return DEFAULT_NEXTID;
|
||||
return rotationApi.map(rot -> maps.indexOf(mapLibrary.getMapByNameOrId(rot.next_map_id()).get()))
|
||||
.flatMap(index -> Optional.ofNullable(index >= 0 ? index : null))
|
||||
.orElseGet(() -> {
|
||||
this.logger.warning("Failed to read next id from " + nextIdFile().toString());
|
||||
return DEFAULT_NEXTID;
|
||||
});
|
||||
}
|
||||
|
||||
for(String line : lines) {
|
||||
|
@ -125,11 +133,7 @@ public class FileRotationProvider extends AbstractRotationProvider {
|
|||
@Override
|
||||
public Future<?> saveRotation(@Nonnull final String name, @Nonnull final RotationState rotation) {
|
||||
this.setRotation(name, rotation);
|
||||
return getExecutorService().submit(new Runnable() {
|
||||
@Override public void run() {
|
||||
FileRotationProvider.this.saveRotationToDisk(name, rotation);
|
||||
}
|
||||
});
|
||||
return getExecutorService().submit(() -> saveRotationToDisk(name, rotation));
|
||||
}
|
||||
|
||||
private void saveRotationToDisk(@Nonnull String name, @Nonnull RotationState rotation) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.nio.file.Path;
|
|||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
|
||||
|
@ -35,9 +36,14 @@ public class FileRotationProviderFactory {
|
|||
|
||||
int priority = provider.getInt("priority", 0);
|
||||
int count = provider.getInt("count", 0);
|
||||
Optional<ServerDoc.Rotation> next = minecraftService.getLocalServer()
|
||||
.rotations()
|
||||
.stream()
|
||||
.filter(rot -> rot.name().equals(name) && mapLibrary.getMapByNameOrId(rot.next_map_id()).isPresent())
|
||||
.findFirst();
|
||||
|
||||
if(Files.isRegularFile(rotationFile)) {
|
||||
providers.add(new RotationProviderInfo(new FileRotationProvider(mapLibrary, name, rotationFile, dataPath), name, priority, count));
|
||||
providers.add(new RotationProviderInfo(new FileRotationProvider(mapLibrary, name, rotationFile, dataPath, next), 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);
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.time.Duration;
|
|||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
|
@ -13,6 +14,7 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
@ -22,6 +24,8 @@ import com.google.common.collect.ImmutableMap;
|
|||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.bukkit.configuration.Configuration;
|
||||
import tc.oc.api.docs.virtual.ServerDoc;
|
||||
import tc.oc.api.minecraft.MinecraftService;
|
||||
import tc.oc.commons.core.logging.ClassLogger;
|
||||
import tc.oc.pgm.map.PGMMap;
|
||||
|
||||
|
@ -30,13 +34,15 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
public class RotationManager {
|
||||
|
||||
private final Logger logger;
|
||||
private final MinecraftService minecraftService;
|
||||
private final Configuration config;
|
||||
private final SortedSet<RotationProviderInfo> providers;
|
||||
private String currentRotationName;
|
||||
private RotationState defaultRotation;
|
||||
|
||||
public RotationManager(Logger logger, Configuration config, PGMMap defaultMap, Collection<RotationProviderInfo> providers) {
|
||||
public RotationManager(Logger logger, MinecraftService minecraftService, Configuration config, PGMMap defaultMap, Collection<RotationProviderInfo> providers) {
|
||||
this.logger = ClassLogger.get(checkNotNull(logger, "logger"), getClass());
|
||||
this.minecraftService = minecraftService;
|
||||
this.config = config;
|
||||
this.providers = Collections.synchronizedSortedSet(Sets.newTreeSet(providers));
|
||||
|
||||
|
@ -85,6 +91,16 @@ public class RotationManager {
|
|||
for(RotationProviderInfo info : this.providers) {
|
||||
info.provider.saveRotation(name, rotation);
|
||||
}
|
||||
|
||||
minecraftService.updateLocalServer((ServerDoc.Rotations) () ->
|
||||
getRotations().entrySet()
|
||||
.stream()
|
||||
.map(entry -> new ServerDoc.Rotation() {
|
||||
public String name() { return entry.getKey(); }
|
||||
public String next_map_id() { return entry.getValue().getNext().getId().slug(); }
|
||||
})
|
||||
.sorted(Comparator.comparing(ServerDoc.Rotation::name, (r1, r2) -> r1.equals(name) ? -1 : 1))
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
public @Nonnull String getCurrentRotationName() {
|
||||
|
@ -136,7 +152,10 @@ public class RotationManager {
|
|||
*/
|
||||
public boolean load(PGMMap defaultMap) {
|
||||
this.defaultRotation = new RotationState(Collections.singletonList(defaultMap), 0);
|
||||
this.currentRotationName = config.getString("rotation.default-name", "default");
|
||||
|
||||
List<ServerDoc.Rotation> rotations = minecraftService.getLocalServer().rotations();
|
||||
this.currentRotationName = rotations.isEmpty() ? config.getString("rotation.default-name", "default") : rotations.get(0).name();
|
||||
|
||||
|
||||
logger.info("Loading rotations from " + providers.size() +
|
||||
" providers. Fallback map is '" + defaultRotation.getMaps().get(0).getName() +
|
||||
|
|
Loading…
Reference in New Issue