Parse rotations from YML files
This commit is contained in:
parent
1c6c6f1c6f
commit
54e1612f51
|
@ -3,6 +3,8 @@ package tc.oc.pgm.rotation;
|
|||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
@ -12,11 +14,12 @@ import java.util.logging.Level;
|
|||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.time.Instant;
|
||||
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import tc.oc.api.docs.virtual.ServerDoc;
|
||||
import tc.oc.commons.core.logging.ClassLogger;
|
||||
import tc.oc.commons.core.util.Joiners;
|
||||
|
@ -25,35 +28,26 @@ import tc.oc.pgm.map.MapLibrary;
|
|||
import tc.oc.pgm.map.PGMMap;
|
||||
|
||||
public class FileRotationProvider extends AbstractRotationProvider {
|
||||
public static final String FILE_NEXTID_SUFFIX = ".next";
|
||||
public static final int DEFAULT_NEXTID = 0;
|
||||
|
||||
private final Logger logger;
|
||||
private final Logger mapLogger;
|
||||
private final MapLibrary mapLibrary;
|
||||
private final String name;
|
||||
private final Path rotationFile;
|
||||
private final Path dataPath;
|
||||
private final Optional<ServerDoc.Rotation> rotationApi;
|
||||
private final boolean shuffle;
|
||||
|
||||
public FileRotationProvider(MapLibrary mapLibrary, String name, Path rotationFile, Path dataPath, Optional<ServerDoc.Rotation> rotationApi) {
|
||||
public FileRotationProvider(MapLibrary mapLibrary, String name, Path rotationFile, Optional<ServerDoc.Rotation> rotationApi, boolean shuffle) {
|
||||
Preconditions.checkNotNull(mapLibrary, "map manager");
|
||||
Preconditions.checkNotNull(rotationFile, "rotation path");
|
||||
Preconditions.checkNotNull(dataPath, "data path");
|
||||
Preconditions.checkArgument(Files.isRegularFile(rotationFile), "rotation path must be a file");
|
||||
Preconditions.checkArgument(Files.isDirectory(dataPath), "data path must be a directory");
|
||||
|
||||
this.logger = ClassLogger.get(PGM.get().getLogger(), getClass());
|
||||
this.mapLogger = PGM.get().getRootMapLogger();
|
||||
this.mapLibrary = mapLibrary;
|
||||
this.name = name;
|
||||
this.rotationFile = rotationFile;
|
||||
this.dataPath = dataPath;
|
||||
this.rotationApi = rotationApi;
|
||||
}
|
||||
|
||||
Path nextIdFile() {
|
||||
return dataPath.resolve(name + FILE_NEXTID_SUFFIX);
|
||||
this.shuffle = shuffle;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -69,7 +63,7 @@ public class FileRotationProvider extends AbstractRotationProvider {
|
|||
|
||||
private RotationState loadRotationFromDisk() throws IOException {
|
||||
List<PGMMap> maps = this.parseRotationNames();
|
||||
int nextId = this.parseNextId(maps);
|
||||
int nextId = this.fetchNextId(maps);
|
||||
|
||||
if(maps.isEmpty()) {
|
||||
throw new IOException(String.format("Rotation '%s' was empty!", name));
|
||||
|
@ -84,36 +78,17 @@ public class FileRotationProvider extends AbstractRotationProvider {
|
|||
return new RotationState(maps, nextId);
|
||||
}
|
||||
|
||||
private int parseNextId(List<PGMMap> maps) {
|
||||
List<String> lines;
|
||||
try {
|
||||
lines = Files.readAllLines(nextIdFile(), Charsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
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) {
|
||||
try {
|
||||
return Integer.parseInt(line);
|
||||
} catch (NumberFormatException e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.warning("Failed to parse next id from " + nextIdFile().toString());
|
||||
return DEFAULT_NEXTID;
|
||||
// TODO: Provide an alternative implementation for no API
|
||||
private int fetchNextId(List<PGMMap> maps) {
|
||||
return rotationApi.map(rot -> maps.indexOf(mapLibrary.getMapByNameOrId(rot.next_map_id()).get()))
|
||||
.flatMap(index -> Optional.ofNullable(index >= 0 ? index : null))
|
||||
.orElse(0);
|
||||
}
|
||||
|
||||
private List<PGMMap> parseRotationNames() throws IOException {
|
||||
List<String> lines = Files.readAllLines(rotationFile, Charsets.UTF_8);
|
||||
|
||||
ImmutableList.Builder<PGMMap> maps = ImmutableList.builder();
|
||||
for(String line : lines) {
|
||||
YamlConfiguration yaml = YamlConfiguration.loadConfiguration(rotationFile.toFile());
|
||||
List<PGMMap> maps = new ArrayList<>();
|
||||
for(String line : yaml.getStringList("maps")) {
|
||||
line = line.trim();
|
||||
if(line.isEmpty()) {
|
||||
continue;
|
||||
|
@ -126,23 +101,14 @@ public class FileRotationProvider extends AbstractRotationProvider {
|
|||
mapLogger.severe("Unknown map '" + line + "' when parsing " + rotationFile.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return maps.build();
|
||||
if(shuffle) Collections.shuffle(maps);
|
||||
return ImmutableList.copyOf(maps);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<?> saveRotation(@Nonnull final String name, @Nonnull final RotationState rotation) {
|
||||
this.setRotation(name, rotation);
|
||||
return getExecutorService().submit(() -> saveRotationToDisk(name, rotation));
|
||||
}
|
||||
|
||||
private void saveRotationToDisk(@Nonnull String name, @Nonnull RotationState rotation) {
|
||||
List<String> nextIdSerialized = ImmutableList.of(Integer.toString(rotation.getNextId()));
|
||||
try {
|
||||
Files.write(nextIdFile(), nextIdSerialized, Charsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
this.logger.log(Level.SEVERE, "Failed to save next id for rotation: " + name, e);
|
||||
}
|
||||
return Futures.immediateFuture(null);
|
||||
}
|
||||
|
||||
private static @Nonnull ExecutorService getExecutorService() {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package tc.oc.pgm.rotation;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
@ -11,6 +13,8 @@ import javax.inject.Inject;
|
|||
|
||||
import org.bukkit.configuration.Configuration;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import tc.oc.api.docs.virtual.ServerDoc;
|
||||
import tc.oc.api.minecraft.MinecraftService;
|
||||
import tc.oc.pgm.map.MapLibrary;
|
||||
|
@ -24,32 +28,52 @@ public class FileRotationProviderFactory {
|
|||
}
|
||||
|
||||
public Set<RotationProviderInfo> parse(MapLibrary mapLibrary, Path dataPath, Configuration config) {
|
||||
ConfigurationSection base = config.getConfigurationSection("rotation.providers.file");
|
||||
ConfigurationSection base = config.getConfigurationSection("rotation.providers");
|
||||
if(base == null) return Collections.emptySet();
|
||||
|
||||
Set<RotationProviderInfo> providers = new HashSet<>();
|
||||
for(String name : base.getKeys(false)) {
|
||||
ConfigurationSection provider = base.getConfigurationSection(name);
|
||||
|
||||
Path rotationFile = Paths.get(provider.getString("path"));
|
||||
if(!rotationFile.isAbsolute()) rotationFile = dataPath.resolve(rotationFile);
|
||||
|
||||
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, 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);
|
||||
for(String pathString : base.getStringList("files")) {
|
||||
Path path = Paths.get(pathString);
|
||||
if(!path.isAbsolute()) path = dataPath.resolve(path);
|
||||
File file = path.toFile();
|
||||
if(file.isDirectory()) {
|
||||
try {
|
||||
Files.walk(path)
|
||||
.filter(Files::isRegularFile)
|
||||
.filter(this::isYaml)
|
||||
.map(Path::toFile)
|
||||
.forEach(f -> providers.add(parse(mapLibrary, f, YamlConfiguration.loadConfiguration(f))));
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if(file.isFile()) {
|
||||
providers.add(parse(mapLibrary, file, YamlConfiguration.loadConfiguration(file)));
|
||||
}
|
||||
}
|
||||
|
||||
return providers;
|
||||
}
|
||||
|
||||
public RotationProviderInfo parse(MapLibrary mapLibrary, File file, YamlConfiguration yaml) {
|
||||
String name = yaml.getString("name", "default");
|
||||
int priority = yaml.getInt("priority", 0);
|
||||
int count = yaml.getInt("count", 0);
|
||||
boolean shuffle = yaml.getBoolean("shuffle", false);
|
||||
Optional<ServerDoc.Rotation> next = minecraftService.getLocalServer()
|
||||
.rotations()
|
||||
.stream()
|
||||
.filter(rot -> rot.name().equals(name) && mapLibrary.getMapByNameOrId(rot.next_map_id()).isPresent())
|
||||
.findFirst();
|
||||
return new RotationProviderInfo(
|
||||
new FileRotationProvider(mapLibrary, name, Paths.get(file.getAbsolutePath()), next, shuffle),
|
||||
name, priority, count
|
||||
);
|
||||
}
|
||||
|
||||
private boolean isYaml(Path path) {
|
||||
try {
|
||||
new YamlConfiguration().load(path.toFile());
|
||||
return true;
|
||||
} catch(Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,7 @@ import javax.annotation.Nonnull;
|
|||
import com.google.common.base.Preconditions;
|
||||
|
||||
public class RotationProviderInfo implements Comparable<RotationProviderInfo> {
|
||||
public final @Nonnull
|
||||
RotationProvider provider;
|
||||
public final @Nonnull RotationProvider provider;
|
||||
public final int priority;
|
||||
public final int count;
|
||||
public final @Nonnull String name;
|
||||
|
|
Loading…
Reference in New Issue