Skip to content

Commit

Permalink
Tweak flags & gamemodes, add gamemode to votebook
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Herrera <[email protected]>
  • Loading branch information
Pablete1234 committed Jul 26, 2023
1 parent 7fa2a4d commit 58b7258
Show file tree
Hide file tree
Showing 21 changed files with 203 additions and 126 deletions.
67 changes: 31 additions & 36 deletions core/src/main/java/tc/oc/pgm/api/map/MapTag.java
Original file line number Diff line number Diff line change
@@ -1,53 +1,51 @@
package tc.oc.pgm.api.map;

import static net.kyori.adventure.text.Component.empty;
import static net.kyori.adventure.text.Component.text;
import static tc.oc.pgm.util.Assert.assertNotNull;
import static tc.oc.pgm.util.Assert.assertTrue;

import java.util.Collections;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.regex.Pattern;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;

/** A "#hashtag" that describes a {@link MapInfo} feature. */
public final class MapTag implements Comparable<MapTag> {
private static final SortedSet<String> TAG_IDS = new TreeSet<>();

private static final Pattern PATTERN = Pattern.compile("^[a-z0-9_-]+$");
private static final String SYMBOL = "#";

private final String id;
private final Component name;
private final Component acronym;
private final boolean gamemode;
private final @Nullable Gamemode gamemode;
private final boolean auxiliary;

public MapTag(
final String id, final String name, final boolean gamemode, final boolean auxiliary) {
this(id, id, name, gamemode, auxiliary);
public MapTag(String id, String name) {
this(id, name, null, true);
}

public MapTag(String id, Gamemode gm, boolean auxiliary) {
this(id, gm.getFullName(), gm, auxiliary);
}

public MapTag(
final String internalId,
final String id,
final String name,
final boolean gamemode,
final boolean auxiliary) {
assertTrue(
PATTERN.matcher(assertNotNull(id)).matches(), name + " must match " + PATTERN.pattern());
private MapTag(String id, String name, @Nullable Gamemode gamemode, boolean auxiliary) {
assertNotNull(id);
assertTrue(PATTERN.matcher(id).matches(), id + " must match " + PATTERN.pattern());
TAG_IDS.add(id);
this.id = id;
if (gamemode) {
Gamemode gm = Gamemode.byId(internalId);
if (gm == null) {
throw new IllegalArgumentException("Gamemode id " + internalId + " not recognized");
}
this.name = text(gm.getFullName());
this.acronym = text(gm.getAcronym());
} else {
this.name = text(name);
this.acronym = empty();
}
this.name = text(name);
this.gamemode = gamemode;
this.auxiliary = auxiliary;
}

public static Set<String> getAllTagIds() {
return Collections.unmodifiableSortedSet(TAG_IDS);
}

/**
* Get a short id for the tag.
*
Expand All @@ -66,26 +64,23 @@ public Component getName() {
return this.name;
}

/**
* Gets an acronym for the tag.
*
* @return An acronym.
*/
public Component getAcronym() {
return this.acronym;
}

/**
* Get whether this tag represents a "gamemode."
*
* @return If a gamemode.
* @return If the tag is for a gamemode.
*/
public boolean isGamemode() {
return this.gamemode != null;
}

/** @return the gamemode if this tag represents one, null otherwise. */
public @Nullable Gamemode getGamemode() {
return this.gamemode;
}

/**
* Get whether this tag is an auxiliary feature.
* Get whether this tag is an auxiliary gamemode, that works as a 2nd level gamemode. Eg: blitz or
* rage are auxiliary due to wool "and blitz", or deathmatch "and rage".
*
* @return If an auxiliary feature.
*/
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/java/tc/oc/pgm/blitz/BlitzModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.jdom2.Document;
import org.jdom2.Element;
import tc.oc.pgm.api.filter.Filter;
import tc.oc.pgm.api.map.Gamemode;
import tc.oc.pgm.api.map.MapModule;
import tc.oc.pgm.api.map.MapTag;
import tc.oc.pgm.api.map.factory.MapFactory;
Expand All @@ -26,7 +27,7 @@
public class BlitzModule implements MapModule<BlitzMatchModule> {

private static final Collection<MapTag> TAGS =
ImmutableList.of(new MapTag("blitz", "Blitz", true, true));
ImmutableList.of(new MapTag("blitz", Gamemode.BLITZ, true));
private final BlitzConfig config;

public BlitzModule(BlitzConfig config) {
Expand Down
3 changes: 1 addition & 2 deletions core/src/main/java/tc/oc/pgm/classes/ClassModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@

public class ClassModule implements MapModule<ClassMatchModule> {

private static final Collection<MapTag> TAGS =
ImmutableList.of(new MapTag("classes", "Classes", false, true));
private static final Collection<MapTag> TAGS = ImmutableList.of(new MapTag("classes", "Classes"));
final String family;
final Map<String, PlayerClass> classes;
final PlayerClass defaultClass;
Expand Down
20 changes: 19 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 @@ -15,6 +15,8 @@
import cloud.commandframework.annotations.Flag;
import cloud.commandframework.annotations.specifier.Greedy;
import cloud.commandframework.annotations.specifier.Range;
import cloud.commandframework.annotations.suggestions.Suggestions;
import cloud.commandframework.context.CommandContext;
import com.google.common.collect.ImmutableList;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
Expand All @@ -36,6 +38,7 @@
import tc.oc.pgm.rotation.MapPoolManager;
import tc.oc.pgm.rotation.pools.MapPool;
import tc.oc.pgm.util.Audience;
import tc.oc.pgm.util.LiquidMetal;
import tc.oc.pgm.util.PrettyPaginatedComponentResults;
import tc.oc.pgm.util.StringUtils;
import tc.oc.pgm.util.named.MapNameStyle;
Expand All @@ -52,7 +55,8 @@ public void maps(
CommandSender sender,
MapLibrary library,
@Argument(value = "page", defaultValue = "1") @Range(min = "1") int page,
@Flag(value = "tags", aliases = "t", repeatable = true) List<String> tags,
@Flag(value = "tags", aliases = "t", repeatable = true, suggestions = "maptags")
List<String> tags,
@Flag(value = "author", aliases = "a") String author,
@Flag(value = "name", aliases = "n") String name,
@Flag(value = "phase", aliases = "p") Phase phase) {
Expand Down Expand Up @@ -115,6 +119,20 @@ public Component format(MapInfo map, int index) {
}.display(audience, ImmutableList.copyOf(maps), page);
}

@Suggestions("maptags")
public List<String> suggestMapTags(CommandContext<CommandSender> sender, String input) {
int commaIdx = input.lastIndexOf(',');

final String prefix = input.substring(0, commaIdx == -1 ? 0 : commaIdx + 1);
final String toComplete =
input.substring(commaIdx + 1).toLowerCase(Locale.ROOT).replace("!", "");

return MapTag.getAllTagIds().stream()
.filter(mt -> LiquidMetal.match(mt, toComplete))
.flatMap(tag -> Stream.of(prefix + tag, prefix + "!" + tag))
.collect(Collectors.toList());
}

private static boolean matchesTags(
MapInfo map, Collection<String> posTags, Collection<String> negTags) {
int matches = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.jdom2.Document;
import org.jdom2.Element;
import tc.oc.pgm.api.PGM;
import tc.oc.pgm.api.map.Gamemode;
import tc.oc.pgm.api.map.MapModule;
import tc.oc.pgm.api.map.MapTag;
import tc.oc.pgm.api.map.factory.MapFactory;
Expand All @@ -27,11 +28,9 @@

public class ControlPointModule implements MapModule<ControlPointMatchModule> {

private static final MapTag CP =
new MapTag("cp", "controlpoint", "Control the Point", true, false);
private static final MapTag KOTH =
new MapTag("koth", "controlpoint", "King of the Hill", true, false);
private static final MapTag PAYLOAD = new MapTag("payload", "Payload", true, false);
private static final MapTag CP = new MapTag("controlpoint", Gamemode.CONTROL_THE_POINT, false);
private static final MapTag KOTH = new MapTag("controlpoint", Gamemode.KING_OF_THE_HILL, false);
private static final MapTag PAYLOAD = new MapTag("payload", Gamemode.PAYLOAD, false);

private final List<ControlPointDefinition> definitions;
private final Collection<MapTag> tags;
Expand Down Expand Up @@ -94,7 +93,8 @@ public ControlPointModule parse(MapFactory factory, Logger logger, Document doc)

for (Element kingEl : doc.getRootElement().getChildren("king")) {
for (Element hillEl : XMLUtils.flattenElements(kingEl, "hills", "hill")) {
tags.add(KOTH);
// CP and KOTH are mutually exclusive, they're the same ID.
if (tags.isEmpty()) tags.add(KOTH);
ControlPointDefinition definition =
ControlPointParser.parseControlPoint(factory, hillEl, Type.HILL, serialNumber);
factory.getFeatures().addFeature(kingEl, definition);
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/java/tc/oc/pgm/core/CoreModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import tc.oc.pgm.api.map.Gamemode;
import tc.oc.pgm.api.map.MapModule;
import tc.oc.pgm.api.map.MapProtos;
import tc.oc.pgm.api.map.MapTag;
Expand All @@ -38,7 +39,7 @@
public class CoreModule implements MapModule<CoreMatchModule> {

private static final Collection<MapTag> TAGS =
ImmutableList.of(new MapTag("dtc", "core", "Destroy the Core", true, false));
ImmutableList.of(new MapTag("core", Gamemode.DESTROY_THE_CORE, false));
protected final List<CoreFactory> coreFactories;

public CoreModule(List<CoreFactory> coreFactories) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.logging.Logger;
import org.jdom2.Document;
import org.jdom2.Element;
import tc.oc.pgm.api.map.Gamemode;
import tc.oc.pgm.api.map.MapModule;
import tc.oc.pgm.api.map.MapProtos;
import tc.oc.pgm.api.map.MapTag;
Expand Down Expand Up @@ -37,7 +38,7 @@
public class DestroyableModule implements MapModule<DestroyableMatchModule> {

private static final Collection<MapTag> TAGS =
ImmutableList.of(new MapTag("dtm", "monument", "Destroy the Monument", true, false));
ImmutableList.of(new MapTag("monument", Gamemode.DESTROY_THE_MONUMENT, false));
protected final List<DestroyableFactory> destroyableFactories;

public DestroyableModule(List<DestroyableFactory> destroyableFactories) {
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/java/tc/oc/pgm/ffa/FreeForAllModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.jdom2.Document;
import org.jdom2.Element;
import tc.oc.pgm.api.PGM;
import tc.oc.pgm.api.map.Gamemode;
import tc.oc.pgm.api.map.MapModule;
import tc.oc.pgm.api.map.MapTag;
import tc.oc.pgm.api.map.factory.MapFactory;
Expand All @@ -24,7 +25,7 @@
public class FreeForAllModule implements MapModule<FreeForAllMatchModule> {

private static final Collection<MapTag> TAGS =
ImmutableList.of(new MapTag("ffa", "Free for All", false, false));
ImmutableList.of(new MapTag("ffa", Gamemode.FREE_FOR_ALL, true));
private final FreeForAllOptions options;

public FreeForAllModule(FreeForAllOptions options) {
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/java/tc/oc/pgm/flag/FlagModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.List;
import java.util.logging.Logger;
import org.jdom2.Document;
import tc.oc.pgm.api.map.Gamemode;
import tc.oc.pgm.api.map.MapModule;
import tc.oc.pgm.api.map.MapTag;
import tc.oc.pgm.api.map.factory.MapFactory;
Expand All @@ -22,7 +23,7 @@
public class FlagModule implements MapModule<FlagMatchModule> {

private static final Collection<MapTag> TAGS =
ImmutableList.of(new MapTag("ctf", "flag", "Capture the Flag", true, false));
ImmutableList.of(new MapTag("flag", Gamemode.CAPTURE_THE_FLAG, false));
private final ImmutableList<PostDefinition> posts;
private final ImmutableList<NetDefinition> nets;
private final ImmutableList<FlagDefinition> flags;
Expand Down
28 changes: 2 additions & 26 deletions core/src/main/java/tc/oc/pgm/map/MapContextImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,24 @@

import static tc.oc.pgm.util.Assert.assertNotNull;

import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import java.lang.ref.SoftReference;
import java.util.Collection;
import java.util.List;
import tc.oc.pgm.api.map.MapContext;
import tc.oc.pgm.api.map.MapInfo;
import tc.oc.pgm.api.map.MapModule;
import tc.oc.pgm.api.map.MapTag;
import tc.oc.pgm.ffa.FreeForAllModule;
import tc.oc.pgm.teams.TeamFactory;
import tc.oc.pgm.teams.TeamModule;

public class MapContextImpl implements MapContext {
private static final MapTag TERRAIN = new MapTag("terrain", "Terrain", false, true);

private final MapInfo info;
private final List<MapModule> modules;

public MapContextImpl(MapInfoImpl info, Collection<MapModule<?>> modules) {
info.context = new SoftReference<>(this);
this.info = info;
this.modules = ImmutableList.copyOf(assertNotNull(modules));

for (MapModule<?> module : this.modules) {
info.tags.addAll(module.getTags());

if (module instanceof TeamModule) {
info.players.clear();
info.players.addAll(
Collections2.transform(((TeamModule) module).getTeams(), TeamFactory::getMaxPlayers));
}

if (module instanceof FreeForAllModule) {
info.players.clear();
info.players.add(((FreeForAllModule) module).getOptions().maxPlayers);
}
}

if (info.getWorld().hasTerrain()) {
info.tags.add(TERRAIN);
}
// Update the map info with stuff derived from modules, like team sizes or tags.
info.setContext(this);
}

public MapInfo getInfo() {
Expand Down
Loading

0 comments on commit 58b7258

Please sign in to comment.