Skip to content

Commit

Permalink
Implement custom objective modes (#1422)
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Herrera <[email protected]>
  • Loading branch information
Pablete1234 authored Nov 3, 2024
1 parent 2e4165e commit c38f894
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 133 deletions.
52 changes: 23 additions & 29 deletions core/src/main/java/tc/oc/pgm/command/ModeCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,22 @@ public void next(Audience audience, ObjectiveModesMatchModule modes) {

if (countdowns.isEmpty()) throwNoResults();

TextComponent.Builder builder =
text().append(translatable("command.nextMode", NamedTextColor.DARK_PURPLE).append(space()));
TextComponent.Builder builder = text()
.append(translatable("command.nextMode", NamedTextColor.DARK_PURPLE).append(space()));

ModeChangeCountdown next = countdowns.get(0);
Duration timeLeft = modes.getCountdown().getTimeLeft(next);

if (timeLeft == null) {
builder.append(text(next.getMode().getPreformattedMaterialName(), NamedTextColor.GOLD));
builder.append(text(next.getMode().getLegacyName(), NamedTextColor.GOLD));
} else if (timeLeft.getSeconds() >= 0) {
builder.append(
text(
WordUtils.capitalize(next.getMode().getPreformattedMaterialName()),
NamedTextColor.GOLD)
.append(space())
.append(text("(", NamedTextColor.AQUA))
.append(
new ModesPaginatedResult(modes)
.formatSingleCountdown(next)
.color(NamedTextColor.AQUA))
.append(text(")", NamedTextColor.AQUA)));
builder.append(text(WordUtils.capitalize(next.getMode().getLegacyName()), NamedTextColor.GOLD)
.append(space())
.append(text("(", NamedTextColor.AQUA))
.append(new ModesPaginatedResult(modes)
.formatSingleCountdown(next)
.color(NamedTextColor.AQUA))
.append(text(")", NamedTextColor.AQUA)));
} else {
throwNoResults();
}
Expand All @@ -83,14 +79,13 @@ public void list(
List<ModeChangeCountdown> modeList = modes.getSortedCountdowns(true);
int resultsPerPage = 8;
int pages = (modeList.size() + resultsPerPage - 1) / resultsPerPage;
Component header =
TextFormatter.paginate(
translatable("command.monumentModes"),
page,
pages,
NamedTextColor.DARK_AQUA,
NamedTextColor.AQUA,
true);
Component header = TextFormatter.paginate(
translatable("command.monumentModes"),
page,
pages,
NamedTextColor.DARK_AQUA,
NamedTextColor.AQUA,
true);

new ModesPaginatedResult(header, resultsPerPage, modes).display(audience, modeList, page);
}
Expand Down Expand Up @@ -122,7 +117,8 @@ public void push(
TextComponent.Builder builder =
text().append(translatable("command.modesPushed", NamedTextColor.GOLD).append(space()));
if (duration.isNegative()) {
builder.append(translatable("command.modesPushedBack", NamedTextColor.GOLD).append(space()));
builder.append(
translatable("command.modesPushedBack", NamedTextColor.GOLD).append(space()));
} else {
builder.append(
translatable("command.modesPushedForwards", NamedTextColor.GOLD).append(space()));
Expand Down Expand Up @@ -152,12 +148,10 @@ public void start(
context.cancel(countdown);
context.start(countdown, time);

TextComponent.Builder builder =
text()
.append(
translatable("command.selectedModePushed", mode.getComponentName())
.color(NamedTextColor.GOLD)
.append(space()));
TextComponent.Builder builder = text()
.append(translatable("command.selectedModePushed", mode.getComponentName())
.color(NamedTextColor.GOLD)
.append(space()));
builder.append(clock(Math.abs(time.getSeconds())).color(NamedTextColor.AQUA));
audience.sendMessage(builder);
}
Expand Down
8 changes: 5 additions & 3 deletions core/src/main/java/tc/oc/pgm/core/Core.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import static net.kyori.adventure.text.format.Style.style;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.util.Collections;
import java.util.Set;
import net.kyori.adventure.text.Component;
Expand Down Expand Up @@ -132,8 +131,10 @@ public Iterable<Location> getProximityLocations(ParticipantState player) {
return proximityLocations;
}

public ImmutableSet<Mode> getModes() {
return this.definition.getModes();
@Override
public boolean isAffectedBy(Mode mode) {
return mode.getMaterialData() != null
&& (this.definition.getModes() == null || this.definition.getModes().contains(mode));
}

public boolean isCoreMaterial(MaterialData material) {
Expand Down Expand Up @@ -241,6 +242,7 @@ public boolean isObjectiveMaterial(Block block) {
return material.matches(block.getState());
}

@Override
public String getModeChangeMessage(Material material) {
return ModeUtils.formatMaterial(material) + " CORE MODE";
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/tc/oc/pgm/core/CoreMatchModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public void lavaProtection(final BlockTransformEvent event) {
@EventHandler(priority = EventPriority.HIGHEST)
public void onObjectiveModeSwitch(final ObjectiveModeChangeEvent event) {
for (Core core : this.cores) {
if (core.getModes() == null || core.getModes().contains(event.getMode())) {
if (core.isAffectedBy(event.getMode())) {
core.replaceBlocks(event.getMode().getMaterialData());
// if at least one of the cores are visible, the mode change message will be sent
if (core.hasShowOption(ShowOption.SHOW_MESSAGES)) {
Expand Down
8 changes: 5 additions & 3 deletions core/src/main/java/tc/oc/pgm/destroyable/Destroyable.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import static tc.oc.pgm.util.nms.NMSHacks.NMS_HACKS;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import java.time.Duration;
import java.time.Instant;
Expand Down Expand Up @@ -171,8 +170,10 @@ public Iterable<Location> getProximityLocations(ParticipantState player) {
return proximityLocations;
}

public ImmutableSet<Mode> getModes() {
return this.definition.getModes();
@Override
public boolean isAffectedBy(Mode mode) {
return mode.getMaterialData() != null
&& (this.definition.getModes() == null || this.definition.getModes().contains(mode));
}

/** Calculate maximum/current health */
Expand Down Expand Up @@ -611,6 +612,7 @@ public boolean isObjectiveMaterial(Block block) {
return this.hasMaterial(MaterialData.block(block));
}

@Override
public String getModeChangeMessage(Material material) {
return ModeUtils.formatMaterial(material) + " OBJECTIVE MODE";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public void processBlockDamage(BlockDamageEvent event) {
@EventHandler(priority = EventPriority.HIGHEST)
public void onObjectiveModeSwitch(final ObjectiveModeChangeEvent event) {
for (Destroyable destroyable : this.destroyables) {
if (destroyable.getModes() == null || destroyable.getModes().contains(event.getMode())) {
if (destroyable.isAffectedBy(event.getMode())) {
double oldCompletion = destroyable.getCompletion();
destroyable.replaceBlocks(event.getMode().getMaterialData());
// if at least one of the destroyables are visible, the mode change message will be sent
Expand Down
6 changes: 4 additions & 2 deletions core/src/main/java/tc/oc/pgm/goals/ModeChangeGoal.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package tc.oc.pgm.goals;

import com.google.common.collect.ImmutableSet;
import org.bukkit.Material;
import org.bukkit.block.Block;
import tc.oc.pgm.modes.Mode;
import tc.oc.pgm.util.material.BlockMaterialData;

public interface ModeChangeGoal<T extends GoalDefinition> extends Goal<T> {

boolean isAffectedBy(Mode mode);

void replaceBlocks(BlockMaterialData newMaterial);

boolean isObjectiveMaterial(Block block);

ImmutableSet<Mode> getModes();
String getModeChangeMessage(Material material);
}
56 changes: 25 additions & 31 deletions core/src/main/java/tc/oc/pgm/modes/Mode.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,51 @@
import static net.kyori.adventure.text.Component.text;

import java.time.Duration;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.Objects;
import java.util.function.Supplier;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.jetbrains.annotations.Nullable;
import tc.oc.pgm.action.Action;
import tc.oc.pgm.api.feature.FeatureInfo;
import tc.oc.pgm.api.filter.Filter;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.features.SelfIdentifyingFeatureDefinition;
import tc.oc.pgm.util.material.BlockMaterialData;

@FeatureInfo(name = "mode")
public class Mode extends SelfIdentifyingFeatureDefinition {
private final BlockMaterialData material;
private final Duration after;
private final @Nullable Filter filter;
private final @Nullable String name;
private final String legacyName;
private final Component componentName;
private final Duration showBefore;

public Mode(final BlockMaterialData material, final Duration after, Duration showBefore) {
this(null, material, after, null, null, showBefore);
}
private final Duration after;
private final Duration showBefore;
private final @Nullable Filter filter;
private final @Nullable BlockMaterialData material;
private final @Nullable Action<? super Match> action;

public Mode(
final @Nullable String id,
final BlockMaterialData material,
final String id,
final @Nullable String name,
final Duration after,
final Duration showBefore,
final @Nullable Filter filter,
final @Nullable String name,
Duration showBefore) {
final @Nullable BlockMaterialData material,
final @Nullable Action<? super Match> action) {
super(id);
this.material = material;
this.after = after;
this.filter = filter;
this.name = name;
this.legacyName = name != null ? name : getPreformattedMaterialName();
this.legacyName = getName(() -> ModeUtils.formatMaterial(material));
this.componentName = text(legacyName, NamedTextColor.RED);
this.after = after;
this.showBefore = showBefore;
this.filter = filter;
this.material = material;
this.action = action;
}

@Override
protected String getDefaultId() {
return makeDefaultId() + "--" + makeId(legacyName);
}

public BlockMaterialData getMaterialData() {
return this.material;
public String getName(Supplier<String> ifNull) {
return Objects.requireNonNullElseGet(this.name, ifNull);
}

public String getLegacyName() {
Expand All @@ -60,10 +58,6 @@ public Component getComponentName() {
return componentName;
}

public String getPreformattedMaterialName() {
return ModeUtils.formatMaterial(this.material);
}

public Duration getAfter() {
return this.after;
}
Expand All @@ -76,11 +70,11 @@ public Duration getShowBefore() {
return this.filter;
}

public @Nullable String getName() {
return this.name;
public @Nullable BlockMaterialData getMaterialData() {
return this.material;
}

public static String makeDefaultId(@Nullable String name, AtomicInteger serial) {
return "--" + makeTypeName(Mode.class) + "-" + makeId(name);
public @Nullable Action<? super Match> getAction() {
return this.action;
}
}
11 changes: 5 additions & 6 deletions core/src/main/java/tc/oc/pgm/modes/ModeUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@

public class ModeUtils {
public static String formatMaterial(Material m) {
switch (m) {
case GOLD_BLOCK:
return "GOLD";
default:
return m.name().replaceAll("_", " ");
}
return switch (m) {
case GOLD_BLOCK -> "GOLD";
default -> m.name().replaceAll("_", " ");
};
}

public static String formatMaterial(MaterialData m) {
if (m == null) return "Unknown mode";
return formatMaterial(m.getItemType());
}
}
41 changes: 22 additions & 19 deletions core/src/main/java/tc/oc/pgm/modes/ObjectiveModeChangeEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

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

import java.util.Collection;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.api.match.event.MatchEvent;
import tc.oc.pgm.core.Core;
import tc.oc.pgm.destroyable.Destroyable;
import tc.oc.pgm.goals.GoalMatchModule;
import tc.oc.pgm.goals.ModeChangeGoal;

public class ObjectiveModeChangeEvent extends MatchEvent {

Expand All @@ -22,27 +22,30 @@ public ObjectiveModeChangeEvent(Match match, final Mode mode) {
super(match);
this.mode = mode;
this.visible = false;
this.name = this.mode.getName(() -> {
ModeChangeGoal<?> objective = getMainObjective();
return objective == null || mode.getMaterialData() == null
? mode.getLegacyName()
: objective.getModeChangeMessage(mode.getMaterialData().getItemType());
});
}

if (this.mode.getName() != null) {
this.name = this.mode.getName();
} else {
GoalMatchModule wins = getMatch().needModule(GoalMatchModule.class);
Collection<Core> cores = wins.getGoals(Core.class).values();
Collection<Destroyable> destroyables = wins.getGoals(Destroyable.class).values();
private ModeChangeGoal<?> getMainObjective() {
GoalMatchModule wins = getMatch().needModule(GoalMatchModule.class);
Destroyable lastDestroyable = null;
int affectedDestroyables = 0;
for (Destroyable destroyable : wins.getGoals(Destroyable.class).values()) {
if (!destroyable.isAffectedBy(mode)) continue;
affectedDestroyables++;
lastDestroyable = destroyable;
}

if (cores.size() > destroyables.size() && cores.size() > 0) {
this.name =
cores.iterator().next().getModeChangeMessage(this.mode.getMaterialData().getItemType());
} else if (destroyables.size() >= cores.size() && destroyables.size() > 0) {
this.name =
destroyables
.iterator()
.next()
.getModeChangeMessage(this.mode.getMaterialData().getItemType());
} else {
this.name = "Unknown Mode";
}
int affectedCores = 0;
for (Core core : wins.getGoals(Core.class).values()) {
if (!core.isAffectedBy(mode)) continue;
if (++affectedCores > affectedDestroyables) return core;
}
return lastDestroyable;
}

public boolean isVisible() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,16 @@ public ModeChangeCountdown getCountdown(Mode mode) {
.orElse(null);
}

@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
@EventHandler(priority = EventPriority.HIGHEST)
public void onObjectiveModeAction(ObjectiveModeChangeEvent event) {
var action = event.getMode().getAction();
if (action != null) {
action.trigger(event.getMatch());
event.setVisible(true);
}
}

@EventHandler(priority = EventPriority.MONITOR)
public void onObjectiveModeChange(ObjectiveModeChangeEvent event) {
if (event.isVisible()) {
Component broadcast = text()
Expand Down
Loading

0 comments on commit c38f894

Please sign in to comment.