Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variant improvements in pools & map command #1250

Merged
merged 2 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions core/src/main/java/tc/oc/pgm/api/map/MapInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.time.LocalDate;
import java.util.Collection;
import java.util.Map;
import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.Nullable;
Expand All @@ -24,8 +25,14 @@ public interface MapInfo extends Comparable<MapInfo>, Cloneable {
*
* @return A variant for the map, if any.
*/
@Nullable
String getVariant();
String getVariantId();

/**
* Get all the variants available for the map
*
* @return a map of variants by their variant id
*/
Map<String, VariantInfo> getVariants();

/** @return the subfolder in which the world is in, or null for the parent folder */
@Nullable
Expand Down Expand Up @@ -187,4 +194,14 @@ default String getStyledNameLegacy(MapNameStyle style, @Nullable CommandSender s
default int compareTo(MapInfo o) {
return getId().compareTo(o.getId());
}

interface VariantInfo {
String getVariantId();

String getMapId();

String getMapName();

String getWorld();
}
}
7 changes: 3 additions & 4 deletions core/src/main/java/tc/oc/pgm/api/map/MapSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import org.jetbrains.annotations.Nullable;
import tc.oc.pgm.api.map.exception.MapMissingException;
import tc.oc.pgm.api.map.includes.MapInclude;
import tc.oc.pgm.map.source.MapRoot;

/** A source where {@link MapInfo} documents and files are downloaded. */
public interface MapSource {
Path FILE = Paths.get("map.xml");
String DEFAULT_VARIANT = "default";

/**
* Get a unique identifier for the source, should be human-readable.
Expand All @@ -24,10 +24,9 @@ public interface MapSource {
/**
* The variant of the map this is for
*
* @return the variant the source, null for the parent source
* @return the variant the source, DEFAULT_VARIANT for the parent source
*/
@Nullable
String getVariant();
String getVariantId();

/**
* A copy of the map source, tailored to a specific variant
Expand Down
34 changes: 33 additions & 1 deletion core/src/main/java/tc/oc/pgm/command/MapCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.stream.Stream;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TextComponent.Builder;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
Expand Down Expand Up @@ -277,6 +278,10 @@ public void map(
}
}

if (map.getVariants().size() > 1) {
audience.sendMessage(formatVariants(map));
}

if (!map.getSource().getRoot().isPrivate() || sender.hasPermission(Permissions.DEBUG)) {
audience.sendMessage(formatMapSource(sender, map));
}
Expand Down Expand Up @@ -356,10 +361,37 @@ private Component formatContribution(Contributor contributor) {
private Component mapInfoLabel(String key) {
return text()
.append(translatable(key, NamedTextColor.DARK_PURPLE, TextDecoration.BOLD))
.append(text(": "))
.append(text(": ", NamedTextColor.WHITE))
.build();
}

private ComponentLike formatVariants(MapInfo map) {
TextComponent.Builder text =
text().append(mapInfoLabel("map.info.variants")).color(NamedTextColor.GOLD);

for (MapInfo.VariantInfo variant : map.getVariants().values()) {
TextComponent variantComp;
if (map.getVariantId().equals(variant.getVariantId())) {
variantComp =
text(variant.getVariantId(), null, TextDecoration.UNDERLINED)
.hoverEvent(
showText(translatable("map.info.variants.current", NamedTextColor.GRAY)));
} else {
variantComp =
text(variant.getVariantId())
.hoverEvent(
showText(
translatable(
"command.maps.hover",
NamedTextColor.GRAY,
text(variant.getMapName(), NamedTextColor.GOLD))))
.clickEvent(runCommand("/map " + variant.getMapName()));
}
text.append(variantComp).append(text(" "));
}
return text;
}

@NotNull
private ComponentLike formatMapSource(CommandSender sender, MapInfo map) {
MapSource source = map.getSource();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public static Document getDocument(MapSource source, MapIncludeProcessor include
private MapFilePreprocessor(MapSource source, MapIncludeProcessor includeProcessor) {
this.source = source;
this.includeProcessor = includeProcessor;
this.variant = source.getVariant() == null ? "default" : source.getVariant();
this.variant = source.getVariantId();
this.includes = new ArrayList<>();
this.constants = new HashMap<>();
}
Expand Down
106 changes: 81 additions & 25 deletions core/src/main/java/tc/oc/pgm/map/MapInfoImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.Component.translatable;
import static tc.oc.pgm.api.map.MapSource.DEFAULT_VARIANT;
import static tc.oc.pgm.util.Assert.assertNotNull;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import java.lang.ref.SoftReference;
Expand Down Expand Up @@ -50,7 +52,9 @@ public class MapInfoImpl implements MapInfo {
private final MapSource source;

private final String id;
private final String variant;
private final String variantId;
private final Map<String, VariantInfo> variants;

private final String worldFolder;
private final Version proto;
private final Version version;
Expand All @@ -77,31 +81,18 @@ public class MapInfoImpl implements MapInfo {

public MapInfoImpl(MapSource source, Element root) throws InvalidXMLException {
this.source = source;
this.variant = source.getVariant();

String tmpName = assertNotNull(Node.fromRequiredChildOrAttr(root, "name").getValueNormalize());
String tmpWorld = null;
if (variant != null) {
Element variantEl =
root.getChildren("variant").stream()
.filter(el -> Objects.equals(variant, el.getAttributeValue("id")))
.findFirst()
.orElseThrow(
() -> new InvalidXMLException("Could not find variant definition", root));

boolean override = XMLUtils.parseBoolean(Node.fromAttr(variantEl, "override"), false);
tmpName = (override ? "" : tmpName + ": ") + variantEl.getTextNormalize();
tmpWorld = variantEl.getAttributeValue("world");
}
this.worldFolder = tmpWorld;
this.variantId = source.getVariantId();
this.variants = createVariantMap(root);

this.name = tmpName;
this.normalizedName = StringUtils.normalize(name);
VariantInfo variant = variants.get(variantId);
if (variant == null) throw new InvalidXMLException("Could not find variant definition", root);

String slug = assertNotNull(root).getChildTextNormalize("slug");
if (slug != null && variant != null) slug += "_" + variant;
this.worldFolder = variant.getWorld();

this.id = assertNotNull(StringUtils.slugify(slug != null ? slug : name));
this.name = variant.getMapName();
this.normalizedName = StringUtils.normalize(name);

this.id = assertNotNull(variant.getMapId());

this.proto = assertNotNull(XMLUtils.parseSemanticVersion(Node.fromRequiredAttr(root, "proto")));
this.version =
Expand All @@ -127,14 +118,31 @@ public MapInfoImpl(MapSource source, Element root) throws InvalidXMLException {
Node.fromLastChildOrAttr(root, "friendlyfire", "friendly-fire"), false);
}

@NotNull
private static Map<String, VariantInfo> createVariantMap(Element root)
throws InvalidXMLException {
ImmutableMap.Builder<String, VariantInfo> variants = ImmutableMap.builder();
variants.put(DEFAULT_VARIANT, new VariantData(root, null));
for (Element el : root.getChildren("variant")) {
VariantData vd = new VariantData(root, el);
variants.put(vd.variantId, vd);
}
return variants.build();
}

@Override
public String getId() {
return id;
}

@Override
public String getVariant() {
return variant;
public String getVariantId() {
return variantId;
}

@Override
public Map<String, VariantInfo> getVariants() {
return variants;
}

@Override
Expand Down Expand Up @@ -353,4 +361,52 @@ protected void setContext(MapContextImpl context) {
}
this.context = new SoftReference<>(context);
}

private static class VariantData implements VariantInfo {
private final String variantId;
private final String mapName;
private final String mapId;
private final String world;

public VariantData(Element root, @Nullable Element variantEl) throws InvalidXMLException {
String name = assertNotNull(Node.fromRequiredChildOrAttr(root, "name").getValueNormalize());
String slug = assertNotNull(root).getChildTextNormalize("slug");

if (variantEl == null) {
this.variantId = DEFAULT_VARIANT;
this.mapName = name;
this.world = null;
} else {
this.variantId = Node.fromRequiredAttr(variantEl, "id").getValue();
if (DEFAULT_VARIANT.equals(variantId)) {
throw new InvalidXMLException("Default variant is not allowed", variantEl);
}
boolean override = XMLUtils.parseBoolean(Node.fromAttr(variantEl, "override"), false);
this.mapName = (override ? "" : name + ": ") + variantEl.getTextNormalize();
this.world = variantEl.getAttributeValue("world");
if (slug != null) slug += "_" + variantId;
}
this.mapId = assertNotNull(StringUtils.slugify(slug != null ? slug : mapName));
}

@Override
public String getVariantId() {
return variantId;
}

@Override
public String getMapId() {
return mapId;
}

@Override
public String getMapName() {
return mapName;
}

@Override
public String getWorld() {
return world;
}
}
}
3 changes: 2 additions & 1 deletion core/src/main/java/tc/oc/pgm/map/MapLibraryImpl.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package tc.oc.pgm.map;

import static tc.oc.pgm.api.map.MapSource.DEFAULT_VARIANT;
import static tc.oc.pgm.util.Assert.assertNotNull;

import java.util.Collections;
Expand Down Expand Up @@ -202,7 +203,7 @@ private MapContext loadMap(MapSource source, @Nullable String mapId) throws MapE
context = factory.load();

// We're not loading a specific map id, and we're not on a variant, load variants
if (mapId == null && source.getVariant() == null) {
if (mapId == null && DEFAULT_VARIANT.equals(source.getVariantId())) {
for (String variant : factory.getVariants()) {
loadMapSafe(source.asVariant(variant), null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ public boolean checkForUpdates() throws MapMissingException {
}

@Override
public String getVariant() {
return variant;
public String getVariantId() {
return variant == null ? DEFAULT_VARIANT : variant;
}

@Override
Expand Down
37 changes: 33 additions & 4 deletions core/src/main/java/tc/oc/pgm/rotation/pools/MapPool.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package tc.oc.pgm.rotation.pools;

import static tc.oc.pgm.api.map.MapSource.DEFAULT_VARIANT;
import static tc.oc.pgm.util.text.TextParser.parseDuration;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.bukkit.configuration.ConfigurationSection;
import tc.oc.pgm.api.PGM;
import tc.oc.pgm.api.map.MapInfo;
import tc.oc.pgm.api.map.MapLibrary;
import tc.oc.pgm.api.map.MapOrder;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.rotation.MapPoolManager;
Expand All @@ -35,7 +38,7 @@ public abstract class MapPool implements MapOrder, Comparable<MapPool> {
section.getInt("players"),
section.getBoolean("dynamic", true),
parseDuration(section.getString("cycle-time", "-1s")),
buildMapList(section.getStringList("maps"), name));
buildMapList(section.getStringList("maps"), section.getStringList("variants"), name));
}

MapPool(
Expand All @@ -57,15 +60,22 @@ public abstract class MapPool implements MapOrder, Comparable<MapPool> {
this.maps = maps;
}

private static List<MapInfo> buildMapList(List<String> mapNames, String poolName) {
private static List<MapInfo> buildMapList(
List<String> mapNames, List<String> variants, String poolName) {
if (mapNames == null) return new ArrayList<>();
if (variants != null) {
int def = variants.indexOf(DEFAULT_VARIANT);
if (def >= 0) variants = variants.subList(0, def);
if (variants.isEmpty()) variants = null;
}

List<MapInfo> mapList = new ArrayList<>(mapNames.size());
MapLibrary maps = PGM.get().getMapLibrary();

for (String mapName : mapNames) {
MapInfo map = PGM.get().getMapLibrary().getMap(mapName);
MapInfo map = maps.getMap(mapName);
if (map != null) {
mapList.add(map);
mapList.add(getVariant(maps, map, variants));
} else {
PGM.get()
.getLogger()
Expand All @@ -77,6 +87,25 @@ private static List<MapInfo> buildMapList(List<String> mapNames, String poolName
return Collections.unmodifiableList(mapList);
}

private static MapInfo getVariant(MapLibrary maps, MapInfo map, List<String> variantIds) {
if (variantIds == null || !map.getVariantId().equals(DEFAULT_VARIANT)) return map;

Map<String, ? extends MapInfo.VariantInfo> variants = map.getVariants();
for (String varId : variantIds) {
MapInfo.VariantInfo variant = variants.get(varId);
if (variant == null) continue;
MapInfo variantMap = maps.getMap(variant.getMapId());
if (variantMap != null) {
return variantMap;
} else {
PGM.get()
.getLogger()
.warning("[MapPool] Failed to get map " + variant.getMapId() + ". Moving on...");
}
}
return map;
}

public MapPoolType getType() {
return type;
}
Expand Down
Loading