Skip to content

Commit

Permalink
Merge branch 'dev' into mercy-limit-min
Browse files Browse the repository at this point in the history
  • Loading branch information
Samuel-Roach authored Sep 3, 2022
2 parents 0559831 + e65c23b commit ea42396
Show file tree
Hide file tree
Showing 25 changed files with 456 additions and 97 deletions.
12 changes: 12 additions & 0 deletions core/src/main/java/tc/oc/pgm/PGMConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.Map;
import java.util.TreeSet;
import java.util.logging.Level;
import javax.annotation.Nullable;
import net.kyori.adventure.text.Component;
import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
Expand Down Expand Up @@ -56,6 +57,7 @@ public final class PGMConfig implements Config {
// map.*
private final List<MapSourceFactory> mapSourceFactories;
private final String mapPoolFile;
private final String includesDirectory;

// countdown.*
private final Duration startTime;
Expand Down Expand Up @@ -159,6 +161,11 @@ public final class PGMConfig implements Config {
mapPoolFile == null || mapPoolFile.isEmpty()
? null
: new File(dataFolder, mapPoolFile).getAbsolutePath();
final String includesDirectory = config.getString("map.includes");
this.includesDirectory =
includesDirectory == null || includesDirectory.isEmpty()
? null
: new File(dataFolder, includesDirectory).getAbsolutePath();

this.startTime = parseDuration(config.getString("countdown.start", "30s"));
this.huddleTime = parseDuration(config.getString("countdown.huddle", "0s"));
Expand Down Expand Up @@ -466,6 +473,11 @@ public String getMapPoolFile() {
return mapPoolFile;
}

@Override
public @Nullable String getIncludesDirectory() {
return includesDirectory;
}

@Override
public Duration getStartTime() {
return startTime;
Expand Down
7 changes: 6 additions & 1 deletion core/src/main/java/tc/oc/pgm/PGMPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import tc.oc.pgm.api.map.MapOrder;
import tc.oc.pgm.api.map.exception.MapException;
import tc.oc.pgm.api.map.factory.MapSourceFactory;
import tc.oc.pgm.api.map.includes.MapIncludeProcessor;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.api.match.MatchManager;
import tc.oc.pgm.api.module.Module;
Expand All @@ -57,6 +58,7 @@
import tc.oc.pgm.listeners.ServerPingDataListener;
import tc.oc.pgm.listeners.WorldProblemListener;
import tc.oc.pgm.map.MapLibraryImpl;
import tc.oc.pgm.map.includes.MapIncludeProcessorImpl;
import tc.oc.pgm.match.MatchManagerImpl;
import tc.oc.pgm.match.NoopVanishManager;
import tc.oc.pgm.namedecorations.ConfigDecorationProvider;
Expand Down Expand Up @@ -85,6 +87,7 @@ public class PGMPlugin extends JavaPlugin implements PGM, Listener {
private Logger gameLogger;
private Datastore datastore;
private MapLibrary mapLibrary;
private MapIncludeProcessor mapIncludeProcessor;
private List<MapSourceFactory> mapSourceFactories;
private MatchManager matchManager;
private MatchTabManager matchTabManager;
Expand Down Expand Up @@ -134,7 +137,8 @@ public void onEnable() {
asyncExecutorService = new BukkitExecutorService(this, true);

mapSourceFactories = new ArrayList<>();
mapLibrary = new MapLibraryImpl(gameLogger, mapSourceFactories);
mapIncludeProcessor = new MapIncludeProcessorImpl(gameLogger);
mapLibrary = new MapLibraryImpl(gameLogger, mapSourceFactories, mapIncludeProcessor);

saveDefaultConfig(); // Writes a config file, if one does not exist.
reloadConfig(); // Populates "this.config", if there is an error, will be null
Expand Down Expand Up @@ -261,6 +265,7 @@ public void reloadConfig() {

mapSourceFactories.clear();
mapSourceFactories.addAll(config.getMapSourceFactories());
mapIncludeProcessor.reload(config);

if (mapOrder != null) {
mapOrder.reload();
Expand Down
8 changes: 8 additions & 0 deletions core/src/main/java/tc/oc/pgm/api/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ public interface Config {
@Nullable
String getMapPoolFile();

/**
* Gets a path to the includes directory.
*
* @return A path to the includes directory, or null for none.
*/
@Nullable
String getIncludesDirectory();

/**
* Gets a duration to wait before starting a match.
*
Expand Down
8 changes: 8 additions & 0 deletions core/src/main/java/tc/oc/pgm/api/map/MapLibrary.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.Iterator;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nullable;
import tc.oc.pgm.api.map.includes.MapIncludeProcessor;

/** A library of {@link MapInfo}s and {@link MapContext}s. */
public interface MapLibrary {
Expand Down Expand Up @@ -45,4 +46,11 @@ public interface MapLibrary {
* @return A {@link MapContext}.
*/
CompletableFuture<MapContext> loadExistingMap(String id);

/**
* Get the {@link MapIncludeProcessor}.
*
* @return A {@link MapIncludeProcessor}
*/
MapIncludeProcessor getIncludeProcessor();
}
11 changes: 11 additions & 0 deletions core/src/main/java/tc/oc/pgm/api/map/MapSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.File;
import java.io.InputStream;
import tc.oc.pgm.api.map.exception.MapMissingException;
import tc.oc.pgm.api.map.includes.MapInclude;

/** A source where {@link MapInfo} documents and files are downloaded. */
public interface MapSource {
Expand Down Expand Up @@ -38,4 +39,14 @@ public interface MapSource {
* @throws MapMissingException If the document can no longer be found.
*/
boolean checkForUpdates() throws MapMissingException;

/**
* Adds an associated {@link MapInclude}
*
* @param include The {@link MapInclude}
*/
void addMapInclude(MapInclude include);

/** Remove all associated {@link MapInclude}, used when reloading document. */
void clearIncludes();
}
37 changes: 37 additions & 0 deletions core/src/main/java/tc/oc/pgm/api/map/includes/MapInclude.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package tc.oc.pgm.api.map.includes;

import java.util.Collection;
import org.jdom2.Content;

/** Represents a snippet of XML that can be referenced for reuse * */
public interface MapInclude {

/**
* Get a unique id which identifies this MapInclude.
*
* @return A unique id
*/
String getId();

/**
* Get the system file time from when this MapInclude file was last modified.
*
* @return Time of last file modification
*/
long getLastModified();

/**
* Gets whether the associated {@link MapInclude} files have changed since last loading.
*
* @param time The current system time
* @return True if given time is newer than last modified time
*/
boolean hasBeenModified(long time);

/**
* Get a collection of {@link Content} which can be merged into an existing {@link Document}
*
* @return a collection of {@link Content}
*/
Collection<Content> getContent();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package tc.oc.pgm.api.map.includes;

import java.util.Collection;
import org.jdom2.Document;
import tc.oc.pgm.api.Config;
import tc.oc.pgm.util.xml.InvalidXMLException;

/** A processor to determine which {@link MapInclude}s should be included when loading a map * */
public interface MapIncludeProcessor {

/**
* Process the given {@link Document} and return a collection of {@link MapInclude}s.
*
* @param document A map document
* @return A collection of map includes, collection will be empty if none are found.
* @throws InvalidXMLException If the given document is not found or able to be parsed.
*/
Collection<MapInclude> getMapIncludes(Document document) throws InvalidXMLException;

/**
* Get a {@link MapInclude} by its id
*
* @param includeId ID of the map include
* @return A {@link MapInclude}
*/
MapInclude getMapIncludeById(String includeId);

/**
* Reload the processor to fetch new map includes or reload existing ones.
*
* @param config A configuration file.
*/
void reload(Config config);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tc.oc.pgm.features;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.SetMultimap;
import java.util.ArrayList;
import java.util.Collection;
Expand Down Expand Up @@ -35,6 +36,19 @@ public Element getNode(FeatureDefinition definition) {
return definitionNodes.get(definition);
}

@Override
public String add(FeatureDefinition obj) {
String id = super.add(obj);
definitions.add(obj);
return id;
}

@Override
public void add(String name, FeatureDefinition obj) {
super.add(name, obj);
this.definitions.add(obj);
}

/**
* Add the given feature to the context with an optional ID. If no ID is given, there is no way to
* retrieve the feature from the context. However, it can still be passed to {@link #getNode} to
Expand Down Expand Up @@ -151,4 +165,9 @@ private <T extends FeatureDefinition> void resolveReference(XMLFeatureReference<
public Collection<FeatureDefinition> getAll() {
return this.definitions;
}

@Override
public <T extends FeatureDefinition> Iterable<T> getAll(Class<T> type) {
return Iterables.filter(definitions, type);
}
}
16 changes: 13 additions & 3 deletions core/src/main/java/tc/oc/pgm/filters/FilterMatchModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
public class FilterMatchModule implements MatchModule, FilterDispatcher, Tickable, Listener {

private final Match match;
private final ContextStore<?> filterContext;
private final ContextStore<? super Filter> filterContext;
private final List<Class<? extends Event>> listeningFor = new LinkedList<>();

private final Map<ReactorFactory<?>, ReactorFactory.Reactor> activeReactors = new HashMap<>();
Expand All @@ -84,7 +84,7 @@ public class FilterMatchModule implements MatchModule, FilterDispatcher, Tickabl
* @param filterContext the context where all {@link Filters} for the relevant match can be found.
* Important to find {@link ReactorFactory}s
*/
public FilterMatchModule(Match match, ContextStore<?> filterContext) {
public FilterMatchModule(Match match, ContextStore<? super Filter> filterContext) {
this.match = match;
this.filterContext = filterContext;
}
Expand All @@ -110,7 +110,7 @@ public void onMatchLoad(MatchLoadEvent event) {
// for dynamic listening. This could potentially result in a need to register a specific event
// listener.
this.filterContext // Check for any factories hidden in filter trees
.getAllUnchecked(Filter.class)
.getAll(Filter.class)
.forEach(this::findAndCreateReactorFactories);

// Then register all event listeners
Expand Down Expand Up @@ -188,6 +188,16 @@ private <F extends Filterable<?>> void register(
throw new IllegalStateException("Cannot register filter listener after match has started");
}

// Ideally this should never happen. All features that try to register a dynamic filter should
// have ensured that the filter can respond dynamically to the scope, at XML parse time.
// However, that does not occur, nothing is validating dynamic filters' scopes at all.
// The proper fix is to have a validation, using FeatureValidation and all features
// that will use a filter dynamically to validate the scope.
if (!filter.respondsTo(scope)) {
throw new IllegalStateException(
"Filter " + filter + " does not respond to " + scope.getSimpleName() + " scope");
}

final ListenerSet listenerSet =
this.listeners.row(filter).computeIfAbsent(scope, s -> new ListenerSet());

Expand Down
5 changes: 3 additions & 2 deletions core/src/main/java/tc/oc/pgm/filters/FilterModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.logging.Logger;
import org.jdom2.Document;
import org.jdom2.Element;
import tc.oc.pgm.api.filter.Filter;
import tc.oc.pgm.api.filter.ReactorFactory;
import tc.oc.pgm.api.map.MapModule;
import tc.oc.pgm.api.map.MapProtos;
Expand All @@ -22,15 +23,15 @@

public class FilterModule implements MapModule<FilterMatchModule> {

private final ContextStore<?> filterContext;
private final ContextStore<? super Filter> filterContext;

/**
* Create the FilterModule.
*
* @param filterContext the context where all {@link Filters} for the relevant match can be found.
* Important to find {@link ReactorFactory}s
*/
private FilterModule(ContextStore<?> filterContext) {
private FilterModule(ContextStore<? super Filter> filterContext) {
this.filterContext = filterContext;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package tc.oc.pgm.filters.operator;

import java.util.Collection;
import java.util.Optional;
import org.bukkit.event.Event;
import tc.oc.pgm.api.filter.query.MatchQuery;
import tc.oc.pgm.features.XMLFeatureReference;
import tc.oc.pgm.filters.matcher.TypedFilter;
Expand Down Expand Up @@ -41,6 +43,11 @@ public boolean isDynamic() {
return filter.isDynamic();
}

@Override
public Collection<Class<? extends Event>> getRelevantEvents() {
return filter.getRelevantEvents();
}

@Override
public Class<? extends MatchQuery> queryType() {
return MatchQuery.class;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
import tc.oc.pgm.api.filter.Filter;
import tc.oc.pgm.api.filter.FilterDefinition;
import tc.oc.pgm.api.map.factory.MapFactory;
import tc.oc.pgm.features.FeatureDefinitionContext;
import tc.oc.pgm.filters.XMLFilterReference;
import tc.oc.pgm.filters.operator.AllowFilter;
import tc.oc.pgm.filters.operator.DenyFilter;
import tc.oc.pgm.filters.operator.InverseFilter;
import tc.oc.pgm.util.MethodParser;
import tc.oc.pgm.util.collection.ContextStore;
import tc.oc.pgm.util.xml.InvalidXMLException;
import tc.oc.pgm.util.xml.Node;

Expand All @@ -21,7 +21,7 @@ public FeatureFilterParser(MapFactory factory) {
}

@Override
public ContextStore<?> getUsedContext() {
public FeatureDefinitionContext getUsedContext() {
return factory.getFeatures();
}

Expand Down
6 changes: 2 additions & 4 deletions core/src/main/java/tc/oc/pgm/filters/parse/FilterParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,11 @@ public FilterParser(MapFactory factory) {
}

/**
* Gets the context used by this parser to store filters/filter references. Must use {@code
* ?}(wildcard) since {@link Filter} does not extend {@link FeatureDefinition}.
* (ContextStore&lt;Filter&gt; vs ContextStore&lt;FeatureDefinition&gt;)
* Gets the context used by this parser to store filters/filter references.
*
* @return the context where this parser puts its parsed filters
*/
public abstract ContextStore<?> getUsedContext();
public abstract ContextStore<? super Filter> getUsedContext();

/**
* The top-level method for parsing an individual filter element. This method should call {@link
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import tc.oc.pgm.filters.matcher.block.BlockFilter;
import tc.oc.pgm.filters.operator.FilterNode;
import tc.oc.pgm.util.MethodParser;
import tc.oc.pgm.util.collection.ContextStore;
import tc.oc.pgm.util.material.matcher.SingleMaterialMatcher;
import tc.oc.pgm.util.xml.InvalidXMLException;
import tc.oc.pgm.util.xml.Node;
Expand All @@ -26,7 +25,7 @@ public LegacyFilterParser(MapFactory factory) {
}

@Override
public ContextStore<?> getUsedContext() {
public FilterContext getUsedContext() {
return this.filterContext;
}

Expand Down
Loading

0 comments on commit ea42396

Please sign in to comment.