/* This file is a part of the SteamWar software. Copyright (C) 2020 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package de.steamwar.fightsystem.winconditions; import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.OneShotStateDependent; import de.steamwar.fightsystem.states.StateDependentListener; import de.steamwar.fightsystem.utils.Message; import org.bukkit.Material; import org.bukkit.entity.EntityType; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityExplodeEvent; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BooleanSupplier; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.ToIntFunction; public class PercentWincondition extends Wincondition implements PrintableWincondition { private final Map teamMap = new HashMap<>(); protected BooleanSupplier explosionFilter = () -> !Config.EnterStages.isEmpty() && Config.EnterStages.get(0) >= Wincondition.getTimeOverCountdown().getTimeLeft(); protected Predicate testBlock = type -> !Config.PercentBlocks.contains(type); protected ToIntFunction totalBlockCalc = team -> { AtomicInteger blocks = new AtomicInteger(); team.getSchemRegion().forEach((x, y, z) -> { if (testBlock.test(Config.world.getBlockAt(x, y, z).getType())) { blocks.getAndIncrement(); } }); return blocks.get(); }; protected Consumer checkWin = team -> { if (getPercent(team) >= Config.PercentWin) { win(Fight.getOpposite(team), "WIN_PERCENT", team.getColoredName()); } }; protected Consumer postEnable = team -> {}; public PercentWincondition(String windescription, Winconditions wincondition) { super(windescription); if (Config.ActiveWinconditions.contains(wincondition)) { printableWinconditions.add(this); percentWincondition = this; } Fight.teams().forEach(team -> new TeamPercent(team, wincondition)); } public Message getDisplay(FightTeam team) { return new Message("BAR_PERCENT", team.getPrefix() + (Math.round(100.0 * getPercent(team)) / 100.0)); } public double getPercent(FightTeam team) { return teamMap.get(team).getPercent(); } protected int getTotalBlocks(FightTeam team) { return teamMap.get(team).totalBlocks; } private class TeamPercent implements Listener { private final FightTeam team; private int totalBlocks = 0; private int currentBlocks = 0; private TeamPercent(FightTeam team, Winconditions wincondition) { this.team = team; new OneShotStateDependent(wincondition, FightState.Running, this::enable); new StateDependentListener(wincondition, FightState.Running, this).register(); teamMap.put(team, this); } @EventHandler public void onEntityExplode(EntityExplodeEvent event) { if (event.getEntityType() == EntityType.FIREBALL || explosionFilter.getAsBoolean() || !team.getExtendRegion().inRegion(event.getEntity().getLocation())) { return; } event.blockList().forEach(block -> { if (testBlock.test(block.getType())) { currentBlocks--; } }); checkWin.accept(team); } private void enable() { totalBlocks = totalBlockCalc.applyAsInt(team); currentBlocks = totalBlocks; postEnable.accept(team); } private double getPercent() { if (currentBlocks >= totalBlocks) { return 0; } return (totalBlocks - currentBlocks) * 100 / (double) totalBlocks; } } }