Skip to content

Commit

Permalink
Add support for variables modifying blitz lives
Browse files Browse the repository at this point in the history
Signed-off-by: Christopher White <[email protected]>
  • Loading branch information
cswhite2000 committed Aug 12, 2023
1 parent c9c4b3e commit bca3408
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 57 deletions.
39 changes: 25 additions & 14 deletions core/src/main/java/tc/oc/pgm/blitz/BlitzMatchModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ public int getNumOfLives(UUID id) {
return lifeManager.getLives(id);
}

public void setLives(MatchPlayer matchPlayer, int lives) {
UUID id = matchPlayer.getId();
if (lives == lifeManager.getLives(id)) return;

lifeManager.setLives(id, lives);
if (this.config.getBroadcastLives()) {
this.showLivesTitle(matchPlayer);
}
}

@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void handleDeath(final MatchPlayerDeathEvent event) {
MatchPlayer victim = event.getVictim();
Expand Down Expand Up @@ -123,23 +133,24 @@ public void handleJoin(final PlayerParticipationStartEvent event) {
@EventHandler
public void handleSpawn(final ParticipantSpawnEvent event) {
if (this.config.getBroadcastLives()) {
int lives = this.lifeManager.getLives(event.getPlayer().getId());
event
.getPlayer()
.showTitle(
title(
empty(),
translatable(
"blitz.livesRemaining",
NamedTextColor.RED,
translatable(
lives == 1 ? "misc.life" : "misc.lives",
NamedTextColor.AQUA,
text(lives))),
Title.Times.times(Duration.ZERO, fromTicks(60), fromTicks(20))));
MatchPlayer matchPlayer = event.getPlayer();
showLivesTitle(matchPlayer);
}
}

public void showLivesTitle(MatchPlayer matchPlayer) {
int lives = this.lifeManager.getLives(matchPlayer.getId());
matchPlayer.showTitle(
title(
empty(),
translatable(
"blitz.livesRemaining",
NamedTextColor.RED,
translatable(
lives == 1 ? "misc.life" : "misc.lives", NamedTextColor.AQUA, text(lives))),
Title.Times.times(Duration.ZERO, fromTicks(60), fromTicks(20))));
}

@EventHandler(priority = EventPriority.MONITOR)
public void onBlitzPlayerEliminated(final BlitzPlayerEliminatedEvent event) {
this.eliminatedPlayers.add(event.getPlayer().getId());
Expand Down
6 changes: 6 additions & 0 deletions core/src/main/java/tc/oc/pgm/blitz/LifeManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,10 @@ public int addLives(UUID player, int dlives) {

return lives;
}

public void setLives(UUID player, int lives) {
assertNotNull(player, "player id");

this.livesLeft.put(player, Math.max(0, lives));
}
}
38 changes: 38 additions & 0 deletions core/src/main/java/tc/oc/pgm/variables/BlitzVariable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package tc.oc.pgm.variables;

import tc.oc.pgm.api.player.MatchPlayer;
import tc.oc.pgm.blitz.BlitzMatchModule;
import tc.oc.pgm.filters.Filterable;

public class BlitzVariable implements Variable<MatchPlayer> {

private final VariableDefinition<MatchPlayer> definition;

public BlitzVariable(VariableDefinition<MatchPlayer> definition) {
this.definition = definition;
}

@Override
public VariableDefinition<MatchPlayer> getDefinition() {
return definition;
}

@Override
public double getValue(Filterable<?> context) {
MatchPlayer matchPlayer = (MatchPlayer) context;
BlitzMatchModule blitzMatchModule = matchPlayer.getMatch().needModule(BlitzMatchModule.class);
return blitzMatchModule.getNumOfLives(matchPlayer.getId());
}

@Override
public void setValue(Filterable<?> context, double value) {
MatchPlayer matchPlayer = (MatchPlayer) context;
BlitzMatchModule blitzMatchModule = matchPlayer.getMatch().needModule(BlitzMatchModule.class);
blitzMatchModule.setLives(matchPlayer, Math.max((int) value, 0));
}

@Override
public VariableType getType() {
return VariableType.LIVES;
}
}
53 changes: 53 additions & 0 deletions core/src/main/java/tc/oc/pgm/variables/DummyVariable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package tc.oc.pgm.variables;

import java.util.HashMap;
import java.util.Map;
import tc.oc.pgm.filters.FilterMatchModule;
import tc.oc.pgm.filters.Filterable;

public class DummyVariable<T extends Filterable<?>> implements Variable<T> {

private final VariableDefinition<T> definition;
private final Map<T, Double> values;

public DummyVariable(VariableDefinition<T> definition) {
this.definition = definition;
this.values = new HashMap<>();
}

@Override
public VariableDefinition<T> getDefinition() {
return definition;
}

@Override
public double getValue(Filterable<?> context) {
return values.computeIfAbsent(getAncestor(context), k -> definition.getDefault());
}

@Override
public void setValue(Filterable<?> context, double value) {
T ctx = getAncestor(context);
values.put(ctx, value);
// For performance reasons, let's avoid launching an event for every variable change
context.getMatch().needModule(FilterMatchModule.class).invalidate(ctx);
}

@Override
public VariableType getType() {
return VariableType.DUMMY;
}

private T getAncestor(Filterable<?> context) {
T filterable = context.getFilterableAncestor(definition.getScope());
if (filterable != null) return filterable;

throw new IllegalStateException(
"Wrong variable scope for '"
+ getId()
+ "', expected "
+ definition.getScope().getSimpleName()
+ " which cannot be found in "
+ context.getClass().getSimpleName());
}
}
46 changes: 6 additions & 40 deletions core/src/main/java/tc/oc/pgm/variables/Variable.java
Original file line number Diff line number Diff line change
@@ -1,52 +1,18 @@
package tc.oc.pgm.variables;

import java.util.HashMap;
import java.util.Map;
import tc.oc.pgm.api.feature.Feature;
import tc.oc.pgm.filters.FilterMatchModule;
import tc.oc.pgm.filters.Filterable;

public class Variable<T extends Filterable<?>> implements Feature<VariableDefinition<T>> {

private final VariableDefinition<T> definition;
private final Map<T, Double> values;

public Variable(VariableDefinition<T> definition) {
this.definition = definition;
this.values = new HashMap<>();
}

@Override
public String getId() {
return definition.getId();
}
public interface Variable<T extends Filterable<?>> extends Feature<VariableDefinition<T>> {

@Override
public VariableDefinition<T> getDefinition() {
return definition;
default String getId() {
return getDefinition().getId();
}

public double getValue(Filterable<?> context) {
return values.computeIfAbsent(getAncestor(context), k -> definition.getDefault());
}
double getValue(Filterable<?> context);

public void setValue(Filterable<?> context, double value) {
T ctx = getAncestor(context);
values.put(ctx, value);
// For performance reasons, let's avoid launching an event for every variable change
context.getMatch().needModule(FilterMatchModule.class).invalidate(ctx);
}
void setValue(Filterable<?> context, double value);

private T getAncestor(Filterable<?> context) {
T filterable = context.getFilterableAncestor(definition.getScope());
if (filterable != null) return filterable;

throw new IllegalStateException(
"Wrong variable scope for '"
+ getId()
+ "', expected "
+ definition.getScope().getSimpleName()
+ " which cannot be found in "
+ context.getClass().getSimpleName());
}
VariableType getType();
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ public class VariableDefinition<T extends Filterable<?>> extends SelfIdentifying

private final Class<T> scope;
private final double def;
private final VariableType variableType;

public VariableDefinition(String id, Class<T> scope, double def) {
public VariableDefinition(String id, Class<T> scope, double def, VariableType variableType) {
super(id);
this.scope = scope;
this.def = def;
this.variableType = variableType;
}

public Class<T> getScope() {
Expand All @@ -23,6 +25,10 @@ public double getDefault() {
return def;
}

public VariableType getVariableType() {
return variableType;
}

@SuppressWarnings("unchecked")
public Variable<T> getVariable(Match match) {
return (Variable<T>) match.getFeatureContext().get(this.getId());
Expand Down
47 changes: 47 additions & 0 deletions core/src/main/java/tc/oc/pgm/variables/VariableType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package tc.oc.pgm.variables;

import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import tc.oc.pgm.api.player.MatchPlayer;
import tc.oc.pgm.filters.Filterable;
import tc.oc.pgm.util.xml.InvalidXMLException;
import tc.oc.pgm.util.xml.Node;

public enum VariableType {
DUMMY(Filterable.class),
LIVES(MatchPlayer.class);

private final Class<?>[] supportedScopes;

VariableType(Class<?>... supportedScopes) {
this.supportedScopes = supportedScopes;
}

public boolean supports(Class<?> cls) {
for (Class<?> supportedScope : supportedScopes) {
if (supportedScope.isAssignableFrom(cls)) {
return true;
}
}
return false;
}

static final Map<String, VariableType> stringTypeMap = new ConcurrentHashMap<>();

static {
for (VariableType value : VariableType.values()) {
stringTypeMap.put(value.name().toLowerCase(Locale.ROOT), value);
}
}

static VariableType parse(Node variableTypeNode, VariableType defaultType)
throws InvalidXMLException {
if (variableTypeNode == null) return defaultType;
VariableType variableType = stringTypeMap.get(variableTypeNode.getValue());
if (variableType != null) return variableType;

throw new InvalidXMLException(
"Unknown Variable Type: " + variableTypeNode.getValue(), variableTypeNode);
}
}
21 changes: 19 additions & 2 deletions core/src/main/java/tc/oc/pgm/variables/VariablesModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import tc.oc.pgm.api.map.factory.MapModuleFactory;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.api.module.exception.ModuleLoadException;
import tc.oc.pgm.api.player.MatchPlayer;
import tc.oc.pgm.filters.Filterable;
import tc.oc.pgm.util.xml.InvalidXMLException;
import tc.oc.pgm.util.xml.Node;
Expand Down Expand Up @@ -74,7 +75,16 @@ public static <T extends Filterable<?>> VariableCache<T> of(
@Override
public VariablesMatchModule createMatchModule(Match match) throws ModuleLoadException {
for (VariableDefinition<?> varDef : this.variables) {
match.getFeatureContext().add(new Variable<>(varDef));
switch (varDef.getVariableType()) {
case DUMMY:
match.getFeatureContext().add(new DummyVariable<>(varDef));
break;
case LIVES:
match
.getFeatureContext()
.add(new BlitzVariable((VariableDefinition<MatchPlayer>) varDef));
break;
}
}

return new VariablesMatchModule();
Expand Down Expand Up @@ -102,8 +112,15 @@ public VariablesModule parse(MapFactory factory, Logger logger, Document doc)
Class<? extends Filterable<?>> scope =
Filterables.parse(Node.fromRequiredAttr(variable, "scope"));
double def = XMLUtils.parseNumber(Node.fromAttr(variable, "default"), Double.class, 0d);
Node variableTypeNode = Node.fromAttr(variable, "type");
VariableType variableType = VariableType.parse(variableTypeNode, VariableType.DUMMY);
if (!variableType.supports(scope)) {
throw new InvalidXMLException(
"VariableType: " + variableType + " Does not support scope: " + scope,
variableTypeNode);
}

VariableDefinition<?> varDef = new VariableDefinition<>(id, scope, def);
VariableDefinition<?> varDef = new VariableDefinition<>(id, scope, def, variableType);
factory.getFeatures().addFeature(variable, varDef);
variables.add(varDef);
}
Expand Down

0 comments on commit bca3408

Please sign in to comment.