ProjectAres/PGM/src/main/java/tc/oc/pgm/score/ScoreBoxFactory.java

160 lines
6.2 KiB
Java

package tc.oc.pgm.score;
import java.util.Map;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.TranslatableComponent;
import org.bukkit.Sound;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import tc.oc.commons.bukkit.chat.NameStyle;
import tc.oc.commons.bukkit.inventory.Slot;
import tc.oc.commons.bukkit.item.ItemUtils;
import tc.oc.commons.core.chat.Component;
import tc.oc.pgm.events.ListenerScope;
import tc.oc.pgm.events.PlayerItemTransferEvent;
import tc.oc.pgm.features.FeatureDefinition;
import tc.oc.pgm.filters.Filter;
import tc.oc.pgm.filters.FilterMatchModule;
import tc.oc.pgm.match.Match;
import tc.oc.pgm.match.MatchPlayer;
import tc.oc.pgm.match.MatchScope;
import tc.oc.pgm.teams.Team;
import tc.oc.pgm.utils.MaterialPattern;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
public interface ScoreBoxFactory extends FeatureDefinition {}
class ScoreBoxFactoryImpl extends FeatureDefinition.Impl implements ScoreBoxFactory {
private final Filter trigger;
private final int score;
private final Filter filter;
private final boolean silent;
private final ImmutableMap<MaterialPattern, Double> redeemables;
public ScoreBoxFactoryImpl(Filter trigger, int score, Filter filter, boolean silent, ImmutableMap<MaterialPattern, Double> redeemables) {
Preconditions.checkNotNull(trigger, "region");
Preconditions.checkNotNull(filter, "filter");
this.trigger = trigger;
this.score = score;
this.filter = filter;
this.silent = silent;
this.redeemables = redeemables;
}
@Override
public void load(Match match) {
new ScoreBox(match);
}
@ListenerScope(MatchScope.RUNNING)
public class ScoreBox implements Listener {
private final Match match;
private final ScoreMatchModule smm;
public ScoreBox(Match match) {
this.match = checkNotNull(match);
this.smm = match.needMatchModule(ScoreMatchModule.class);
match.registerEvents(this);
match.needMatchModule(FilterMatchModule.class)
.onRise(MatchPlayer.class, trigger, player -> {
if(canScore(player)) {
score(player, score + redeemItems(player));
}
});
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerAcquireItem(final PlayerItemTransferEvent event) {
match.interactor(event.getPlayer()).ifPresent(player -> {
if(event.isAcquiring() &&
canScore(player) &&
trigger.query(player).isAllowed()) {
score(player, redeemItems(player));
}
});
}
private boolean canScore(MatchPlayer player) {
return player.canInteract() &&
filter.query(player).isAllowed();
}
/**
* If given item is redeemed, change its amount and return the points awarded (which may be 0 or negative)
*
* Return NaN if the item is not redeemed.
*/
private double redeemItem(ItemStack stack) {
if(stack != null) {
for(Map.Entry<MaterialPattern, Double> entry : ((Map<MaterialPattern, Double>) redeemables).entrySet()) {
if(entry.getKey().matches(stack.getData())) {
final double points = entry.getValue() * stack.getAmount();
stack.setAmount(0);
return points;
}
}
}
return Double.NaN;
}
private double redeemItems(MatchPlayer player) {
if(redeemables.isEmpty()) return 0;
final PlayerInventory inventory = player.getInventory();
return Slot.Player.player()
.map(slot -> {
final ItemStack item = slot.getItem(inventory);
final double points = redeemItem(item);
if(Double.isNaN(points)) {
return 0D;
} else {
// Note that redeeming a zero-amount stack will remove the item, but give no points
slot.putItem(inventory, ItemUtils.something(item).orElse(null));
return points;
}
})
.reduce(0D, (a, b) -> a + b);
}
private void score(MatchPlayer player, double points) {
checkState(player.isParticipating());
if(points == 0) return;
final int integerPoints = (int) points; // can be negative
if(!silent && integerPoints != 0) {
player.playSound(Sound.ENTITY_PLAYER_LEVELUP, 1, 1);
player.getMatch().sendMessage(
new Component(
new TranslatableComponent(
player.getCompetitor() instanceof Team ? "match.score.scorebox.team"
: "match.score.scorebox.individual",
player.getStyledName(NameStyle.VERBOSE),
new TranslatableComponent(
integerPoints == 1 ? "points.singularCompound"
: "points.pluralCompound",
new Component(integerPoints, ChatColor.DARK_AQUA)
),
new Component(player.getParty().getComponentName())
), ChatColor.GRAY
)
);
}
smm.incrementScore(player.getCompetitor(), points);
}
}
}