diff --git a/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/CitadelUtility.java b/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/CitadelUtility.java index a9abf4485..3a0724ce4 100644 --- a/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/CitadelUtility.java +++ b/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/CitadelUtility.java @@ -8,9 +8,12 @@ import net.md_5.bungee.api.chat.hover.content.Text; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import vg.civcraft.mc.citadel.acidtypes.AcidType; +import vg.civcraft.mc.citadel.model.AcidManager; import vg.civcraft.mc.citadel.model.Reinforcement; import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; import vg.civcraft.mc.civmodcore.inventory.items.ItemMap; @@ -212,6 +215,26 @@ public class CitadelUtility { Citadel.getInstance().getLogger().info(player.getName() + " created reinforcement with " + type.getName() + " for " + block.getType().toString() + " at " + block.getLocation().toString()); } + // warn if acid cannot complete + if (Citadel.getInstance().getAcidManager().isPossibleAcidBlock(block)) { + AcidManager acidMan = Citadel.getInstance().getAcidManager(); + AcidType acidType = acidMan.getAcidTypeFromMaterial(block.getType()); + for (BlockFace blockFace : acidType.blockFaces()) { + Block relativeBlock = block.getRelative(blockFace); + Reinforcement relativeReinforcement = ReinforcementLogic.getReinforcementProtecting(relativeBlock); + if ( + relativeReinforcement == null + || !relativeReinforcement.getType().canBeReinforced(relativeBlock.getType()) + || (acidMan.isPossibleAcidBlock(relativeBlock) && acidMan.isAcidOnSameGroup(newRein, relativeReinforcement)) + ) { + continue; + } + if (!acidMan.canAcidBlock(type, relativeReinforcement.getType())) { + CitadelUtility.sendAndLog(player, ChatColor.RED, + "The " + blockFace.toString() + " acid will fail as it cannot acid tougher reinforcements!"); + } + } + } ReinforcementLogic.createReinforcement(newRein); return false; } diff --git a/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/command/Acid.java b/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/command/Acid.java index e2ff43d9b..f31ef0c1a 100644 --- a/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/command/Acid.java +++ b/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/command/Acid.java @@ -4,8 +4,10 @@ import co.aikar.commands.BaseCommand; import co.aikar.commands.annotation.CommandAlias; import co.aikar.commands.annotation.Description; import java.util.Iterator; +import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.logging.Level; +import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.block.Block; @@ -54,16 +56,25 @@ public class Acid extends BaseCommand { "You do not have sufficient permission to use acid blocks on this group."); return; } - long neededTime = acidMan.getRemainingAcidMaturationTime(reinforcement); - if (neededTime > 0) { - CitadelUtility.sendAndLog(p, ChatColor.RED, "That acid block will be mature in " - + TextUtil.formatDuration(neededTime, TimeUnit.MILLISECONDS)); - return; + + Map remainingTimes = acidMan.getRemainingAcidMaturationTime(reinforcement); + Map filteredEntries = remainingTimes.entrySet().stream() + .filter(entry -> entry.getValue() <= 0) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + for (BlockFace blockFace : remainingTimes.keySet()) { + Block relativeBlock = block.getRelative(blockFace); + Reinforcement relativeReinforcement = ReinforcementLogic.getReinforcementProtecting(relativeBlock); + + if (filteredEntries.isEmpty()) { + if (relativeReinforcement != null && !acidMan.canAcidBlock(reinforcement.getType(), relativeReinforcement.getType())) { + CitadelUtility.sendAndLog(p, ChatColor.RED, String.format("The acid facing %s will fail!", blockFace)); + } + CitadelUtility.sendAndLog(p, ChatColor.RED, String.format("This acid block is not ready yet.")); + return; + } } - AcidType acidType = acidMan.getAcidTypeFromMaterial(block.getType()); - - for (BlockFace blockFace : acidType.blockFaces()) { + for (BlockFace blockFace : filteredEntries.keySet()) { Block relativeBlock = block.getRelative(blockFace); Reinforcement relativeReinforcement = ReinforcementLogic.getReinforcementProtecting(relativeBlock); @@ -71,7 +82,7 @@ public class Acid extends BaseCommand { relativeReinforcement == null || !relativeReinforcement.getType().canBeReinforced(relativeBlock.getType()) || !acidMan.canAcidBlock(reinforcement.getType(), relativeReinforcement.getType()) - || acidMan.isPossibleAcidBlock(relativeBlock) + || (acidMan.isPossibleAcidBlock(relativeBlock) && acidMan.isAcidOnSameGroup(reinforcement, relativeReinforcement)) ) { continue; } diff --git a/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/command/ReinforcementsGUI.java b/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/command/ReinforcementsGUI.java index b343ecc75..d61e6bc28 100644 --- a/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/command/ReinforcementsGUI.java +++ b/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/command/ReinforcementsGUI.java @@ -4,7 +4,9 @@ import co.aikar.commands.BaseCommand; import co.aikar.commands.annotation.CommandAlias; import co.aikar.commands.annotation.Description; import java.text.DecimalFormat; +import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -14,9 +16,11 @@ import java.util.stream.Collectors; import net.kyori.adventure.text.Component; import org.bukkit.ChatColor; import org.bukkit.Material; +import org.bukkit.block.BlockFace; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.acidtypes.AcidType; import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; import vg.civcraft.mc.civmodcore.inventory.gui.DecorationStack; import vg.civcraft.mc.civmodcore.inventory.gui.IClickable; @@ -46,20 +50,28 @@ public class ReinforcementsGUI extends BaseCommand { Collections.sort(disallowedTypes, (o1, o2) -> Double.compare(o1.getHealth(), o2.getHealth())); List clicks = new LinkedList<>(); - clicks.addAll(getClicks(allowedTypes, true)); + clicks.addAll(getMaterialClicks(allowedTypes, true)); if (disallowedTypes.size() > 0) { for (int i = 0; i < 18 - (allowedTypes.size() % 9); i++) { clicks.add(new DecorationStack(Material.AIR)); } } - clicks.addAll(getClicks(disallowedTypes, false)); + clicks.addAll(getMaterialClicks(disallowedTypes, false)); + + List acidTypes = Citadel.getInstance().getAcidManager().getAcidTypes(); + // check if dimensional reinforcements + int size = disallowedTypes.size() > 0 ? disallowedTypes.size() : allowedTypes.size(); + for (int i = 0; i < 18 - (size % 9); i++) { + clicks.add(new DecorationStack(Material.AIR)); + } + clicks.addAll(getAcidTypeClicks(acidTypes)); MultiPageView pageView = new MultiPageView(sender, clicks, ChatColor.BLUE + "Reinforcements", true); pageView.showScreen(); } - private List getClicks(List types, boolean allowed) { + private List getMaterialClicks(List types, boolean allowed) { List clickables = new LinkedList<>(); for (ReinforcementType type : types) { @@ -92,4 +104,21 @@ public class ReinforcementsGUI extends BaseCommand { return clickables; } + + private List getAcidTypeClicks(List acidTypes) { + List clickables = new ArrayList<>(); + + for (AcidType acidType : acidTypes) { + ItemStack is = new ItemStack(acidType.material()); + String blockName = ItemUtils.getItemName(acidType.material()); + ItemUtils.setComponentDisplayName(is, Component.text(ChatColor.RED + blockName)); + ItemUtils.addLore(is, ChatColor.GOLD + "Acid faces: " + (acidType.blockFaces().stream().map(BlockFace::toString).collect(Collectors.joining(", ")))); + ItemUtils.addLore(is, ChatColor.GOLD + "Maturation modifier: " + format.format(acidType.modifier()) + "x"); + + IClickable click = new DecorationStack(is); + clickables.add(click); + } + + return clickables; + } } diff --git a/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/listener/ModeListener.java b/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/listener/ModeListener.java index d1b24cfa1..21c040c49 100644 --- a/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/listener/ModeListener.java +++ b/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/listener/ModeListener.java @@ -2,6 +2,7 @@ package vg.civcraft.mc.citadel.listener; import java.awt.*; import java.text.DecimalFormat; +import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; import net.kyori.adventure.text.Component; @@ -10,6 +11,8 @@ import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Color; import org.bukkit.GameMode; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -270,11 +273,26 @@ public class ModeListener implements Listener { AcidManager acidMan = Citadel.getInstance().getAcidManager(); if (acidMan.isPossibleAcidBlock(e.getClickedBlock())) { sb.append(ChatColor.GOLD); - long remainingTime = acidMan.getRemainingAcidMaturationTime(rein); - if (remainingTime == 0) { - sb.append("Acid ready"); - } else { - sb.append(String.format("%sAcid block mature in %s", ChatColor.YELLOW, TextUtil.formatDuration(remainingTime, TimeUnit.MILLISECONDS))); + Map times = acidMan.getRemainingAcidMaturationTime(rein); + Block acidBlock = rein.getLocation().getBlock(); + for (Map.Entry entry : times.entrySet()) { + Reinforcement relativeReinforcement = ReinforcementLogic.getReinforcementProtecting(acidBlock.getRelative(entry.getKey())); + if (relativeReinforcement != null) { + if (!acidMan.canAcidBlock(rein.getType(), relativeReinforcement.getType())) { + sb.append(String.format("\n%s%s acid will fail!", ChatColor.RED, entry.getKey())); + continue; + } + if (acidMan.isPossibleAcidBlock(relativeReinforcement.getLocation().getBlock()) && acidMan.isAcidOnSameGroup(rein, relativeReinforcement)) { + continue; + } + if (entry.getValue() == 0) { + sb.append(String.format("\n%s%s acid ready", ChatColor.YELLOW, entry.getKey())); + continue; + } + sb.append(String.format("\n%s%s acid will be ready in %s", + ChatColor.YELLOW, entry.getKey(), + TextUtil.formatDuration(entry.getValue(), TimeUnit.MILLISECONDS))); + } } } if (e.getPlayer().hasPermission("citadel.admin")) { diff --git a/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/model/AcidManager.java b/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/model/AcidManager.java index 9a07e31b7..ec85a8032 100644 --- a/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/model/AcidManager.java +++ b/plugins/citadel-paper/src/main/java/vg/civcraft/mc/citadel/model/AcidManager.java @@ -2,7 +2,9 @@ package vg.civcraft.mc.citadel.model; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -32,15 +34,25 @@ public class AcidManager { } /** - * Gets remaining time needed to mature acid block in milli seconds. If the acid + * Checks if acid faces are on the same group + * + * @param acidBlock acid Reinforcement type to check for + * @param victim victim block Reinforcement type + * @return True if victim and acid block are on the same group + */ + public boolean isAcidOnSameGroup(Reinforcement acidBlock, Reinforcement victim) { + return acidBlock.getGroup().equals(victim.getGroup()); + } + + /** + * Gets remaining time needed to mature acid in milli seconds for each block face. If the acid * is ready 0 will be returned * * @param rein Reinforcement to check for - * @return Remaining time in milli seconds or 0 if the acid is ready + * @return Current block face being checked, remaining time in milli seconds or 0 if the acid is ready */ - public long getRemainingAcidMaturationTime(Reinforcement rein) { + public Map getRemainingAcidMaturationTime(Reinforcement rein) { Block acidBlock = rein.getLocation().getBlock(); - Block targetBlock = acidBlock.getRelative(BlockFace.UP); double acidMultiplier = acidTypes.stream() .filter(acidType -> acidType.material() == acidBlock.getType()) @@ -48,15 +60,30 @@ public class AcidManager { .map(AcidType::modifier) .orElse(1D); + List acidFaces = acidTypes.stream() + .filter(acidType -> acidType.material() == acidBlock.getType()) + .findFirst() + .map(AcidType::blockFaces) + .orElse(List.of(BlockFace.UP)); + double decayMultiplier = 1; - if (!MaterialUtils.isAir(targetBlock.getType())) { - Reinforcement targetBlockRein = ReinforcementLogic.getReinforcementAt(targetBlock.getLocation()); - if (targetBlockRein != null) { + Map remainingTimes = new HashMap<>(); + for (BlockFace face : acidFaces) { + Block relativeBlock = acidBlock.getRelative(face); + Reinforcement targetBlockRein = ReinforcementLogic.getReinforcementAt(relativeBlock.getLocation()); + if ( + targetBlockRein != null + && !MaterialUtils.isAir(relativeBlock.getType()) + ) { decayMultiplier = ReinforcementLogic.getDecayDamage(targetBlockRein); } + + long targetAcidTime = (targetBlockRein != null) ? targetBlockRein.getType().getAcidTime() : rein.getType().getAcidTime(); + long totalTime = Math.round(targetAcidTime / decayMultiplier * acidMultiplier); + long remainingTime = Math.max(0, totalTime - rein.getAge()); + remainingTimes.put(face, remainingTime); } - long totalTime = Math.round(rein.getType().getAcidTime() / decayMultiplier * acidMultiplier); - return Math.max(0, totalTime - rein.getAge()); + return remainingTimes; } /** @@ -79,4 +106,8 @@ public class AcidManager { .findFirst() .orElseThrow(); } + + public List getAcidTypes() { + return acidTypes; + } }