Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 6 additions & 31 deletions src/main/java/net/tfminecraft/rpcharacters/loaders/PvpLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@ public final class PvpLoader implements LoaderInterface {
private static boolean strikeDecayEnabled = false;
private static int strikeDecayDays = 14;
private static int helmetDonSeconds = 1;
private static int chestplateDonSeconds = 20;
private static int leggingsDonSeconds = 12;
private static int bootsDonSeconds = 8;
private static int chestplateDonSeconds = 4;
private static int leggingsDonSeconds = 3;
private static int bootsDonSeconds = 2;
private static int donSlownessAmplifier = 1;
private static int recentArmourSeconds = 180;

private static String startWarning = "&ePvP will start in {seconds} seconds! &7Deaths in this fight can cost strikes.";
private static String countdown = "&c{count}";
Expand All @@ -44,14 +43,11 @@ public final class PvpLoader implements LoaderInterface {
private static String noCharacter = "&cYou need an active character to set PvP mode.";
private static String current = "&7This character's PvP mode: {mode}";
private static String playersOnly = "&cPlayers only.";
private static String armourLocked = "&cYou can't put armour on during a PvP situation.";
private static String donProgress = "&eFastening your {piece} &7[{bar}&7] &f{seconds}s{queued}";
private static String donQueued = " &7(+{count} queued)";
private static String donDone = "&aYou've put on your {piece}.";
private static String donInterrupted = "&cYou stopped fastening your {piece}.";
private static String donMissing = "&cYou no longer have the {piece} you were putting on.";
private static String armourStripped = "&cYou hadn't finished fastening your {pieces}. It's back in your inventory.";
private static String armourStrippedOthers = "&7{name} hadn't finished fastening their armour.";

@Override
public void load(File configFile) {
Expand All @@ -74,11 +70,10 @@ public void load(File configFile) {
strikeDecayEnabled = config.getBoolean("strikes.decay.enabled", false);
strikeDecayDays = Math.max(1, config.getInt("strikes.decay.days", 14));
helmetDonSeconds = Math.max(0, config.getInt("armour.don-seconds.helmet", 1));
chestplateDonSeconds = Math.max(0, config.getInt("armour.don-seconds.chestplate", 20));
leggingsDonSeconds = Math.max(0, config.getInt("armour.don-seconds.leggings", 12));
bootsDonSeconds = Math.max(0, config.getInt("armour.don-seconds.boots", 8));
chestplateDonSeconds = Math.max(0, config.getInt("armour.don-seconds.chestplate", 4));
leggingsDonSeconds = Math.max(0, config.getInt("armour.don-seconds.leggings", 3));
bootsDonSeconds = Math.max(0, config.getInt("armour.don-seconds.boots", 2));
donSlownessAmplifier = Math.max(-1, config.getInt("armour.slowness-amplifier", 1));
recentArmourSeconds = Math.max(0, config.getInt("armour.recent-seconds", 180));

startWarning = config.getString("messages.start-warning", startWarning);
countdown = config.getString("messages.countdown", countdown);
Expand All @@ -94,14 +89,11 @@ public void load(File configFile) {
noCharacter = config.getString("messages.no-character", noCharacter);
current = config.getString("messages.current", current);
playersOnly = config.getString("messages.players-only", playersOnly);
armourLocked = config.getString("messages.armour-locked", armourLocked);
donProgress = config.getString("messages.don-progress", donProgress);
donQueued = config.getString("messages.don-queued", donQueued);
donDone = config.getString("messages.don-done", donDone);
donInterrupted = config.getString("messages.don-interrupted", donInterrupted);
donMissing = config.getString("messages.don-missing", donMissing);
armourStripped = config.getString("messages.armour-stripped", armourStripped);
armourStrippedOthers = config.getString("messages.armour-stripped-others", armourStrippedOthers);
}

public static int getStartRadius() {
Expand Down Expand Up @@ -233,15 +225,6 @@ public static int getDonSlownessAmplifier() {
return donSlownessAmplifier;
}

/** 0 when /pvp start takes nothing off. */
public static long getRecentArmourMs() {
return recentArmourSeconds * 1000L;
}

public static String getArmourLocked() {
return armourLocked;
}

public static String getDonProgress() {
return donProgress;
}
Expand All @@ -261,12 +244,4 @@ public static String getDonInterrupted() {
public static String getDonMissing() {
return donMissing;
}

public static String getArmourStripped() {
return armourStripped;
}

public static String getArmourStrippedOthers() {
return armourStrippedOthers;
}
}
94 changes: 2 additions & 92 deletions src/main/java/net/tfminecraft/rpcharacters/pvp/ArmourDonning.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -52,9 +50,7 @@
* looks likely. Pieces are fastened one after another while the player is
* slowed. Taking or dealing damage, sprinting, dying or logging out stops it.
* Masks, heads and elytras go on at once, and creative or spectator players
* are never delayed. {@code /pvp start} takes off any body armour put on
* recently. Those left in full body armour keep their helmet free for roleplay;
* anyone else also loses whatever they recently put on their head.
* are never delayed.
*/
public final class ArmourDonning implements Listener {

Expand All @@ -68,7 +64,6 @@ public final class ArmourDonning implements Listener {
private static final long ACTION_BAR_TICKS = 40L;

private static final Map<UUID, Donning> donning = new HashMap<>();
private static final Map<UUID, EnumMap<ArmorType, Long>> equippedAt = new HashMap<>();
private static final Set<UUID> completing = new HashSet<>();
private static BukkitTask ticker;

Expand Down Expand Up @@ -113,13 +108,6 @@ static boolean isArmourPiece(ItemStack item) {
return armour && !MaskService.isMaskItem(item);
}

/** Wearing a real chestplate, leggings and boots. The helmet doesn't count. */
public static boolean wearsBodyArmour(Player player) {
PlayerInventory inventory = player.getInventory();
return isArmourPiece(inventory.getChestplate()) && isArmourPiece(inventory.getLeggings())
&& isArmourPiece(inventory.getBoots());
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onArmorEquip(ArmorEquipEvent event) {
Player player = event.getPlayer();
Expand All @@ -135,22 +123,6 @@ public void onArmorEquip(ArmorEquipEvent event) {
queue(player, event.getType(), piece, event.getMethod(), System.currentTimeMillis());
}

/** Remember when each piece went on, for {@link #takeOffRecent}. */
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onArmorChanged(ArmorEquipEvent event) {
Player player = event.getPlayer();
if (player == null || event.getType() == null) {
return;
}
EnumMap<ArmorType, Long> times = equippedAt.computeIfAbsent(player.getUniqueId(),
id -> new EnumMap<>(ArmorType.class));
if (event.getNewArmorPiece() == null) {
times.remove(event.getType());
} else {
times.put(event.getType(), System.currentTimeMillis());
}
}

/**
* Right-clicking armour while that slot is full swaps the two pieces without
* an {@link ArmorEquipEvent}. Undo the swap a tick later and fasten it instead.
Expand Down Expand Up @@ -187,18 +159,13 @@ static void undoSwap(Player player, ArmorType type, int handSlot, ItemStack want
|| !previous.isSimilar(inventory.getItem(handSlot))) {
return;
}
boolean locked = PvpSituations.locksArmour(player.getUniqueId(), type);
if (!locked && !delays(player, type, wanted)) {
if (!delays(player, type, wanted)) {
return;
}
ItemStack swappedOn = armour(inventory, type);
setArmour(inventory, type, inventory.getItem(handSlot));
inventory.setItem(handSlot, swappedOn);
player.updateInventory();
if (locked) {
RPTexts.send(player, PvpLoader.getArmourLocked());
return;
}
queue(player, type, swappedOn, ArmorEquipEvent.EquipMethod.HOTBAR, System.currentTimeMillis());
}

Expand Down Expand Up @@ -235,57 +202,6 @@ public void onQuit(PlayerQuitEvent event) {
stop(event.getPlayer(), false);
}

/**
* For {@code /pvp start}: stop fastening, and take off any body armour put on
* within {@code armour.recent-seconds}. Someone still in full body armour keeps
* their helmet. Anyone else also loses a helmet, mask or head put on in that
* time, since they can't put one on during the fight. Returns whether anything
* came off.
*/
public static boolean takeOffRecent(Player player, long nowMs) {
stop(player, true);
EnumMap<ArmorType, Long> times = equippedAt.get(player.getUniqueId());
long windowMs = PvpLoader.getRecentArmourMs();
if (times == null || windowMs <= 0L) {
return false;
}
List<String> pieces = new ArrayList<>();
for (ArmorType type : ArmorType.values()) {
if (type != ArmorType.HELMET && takeOffIfRecent(player, times, type, nowMs, windowMs)) {
pieces.add(pieceName(type));
}
}
if (!wearsBodyArmour(player)) {
String head = isArmourPiece(player.getInventory().getHelmet()) ? pieceName(ArmorType.HELMET) : "headwear";
if (takeOffIfRecent(player, times, ArmorType.HELMET, nowMs, windowMs)) {
pieces.add(head);
}
}
if (pieces.isEmpty()) {
return false;
}
RPTexts.send(player, PvpLoader.getArmourStripped().replace("{pieces}", String.join(", ", pieces)));
return true;
}

/** Body slots only count real armour; anything worn on the head counts. */
private static boolean takeOffIfRecent(Player player, EnumMap<ArmorType, Long> times, ArmorType type,
long nowMs, long windowMs) {
Long at = times.get(type);
if (at == null || nowMs - at > windowMs) {
return false;
}
times.remove(type);
PlayerInventory inventory = player.getInventory();
ItemStack worn = armour(inventory, type);
if (type == ArmorType.HELMET ? isEmpty(worn) : !isArmourPiece(worn)) {
return false;
}
setArmour(inventory, type, null);
giveBack(player, worn);
return true;
}

private static boolean delays(Player player, ArmorType type, ItemStack piece) {
GameMode mode = player.getGameMode();
return mode != GameMode.CREATIVE && mode != GameMode.SPECTATOR
Expand Down Expand Up @@ -344,11 +260,6 @@ static void tick(long nowMs) {

private static void finish(Player player, Donning state, long nowMs) {
Piece piece = state.current;
if (PvpSituations.locksArmour(player.getUniqueId(), piece.type())) {
RPTexts.send(player, PvpLoader.getArmourLocked());
stop(player, false);
return;
}
if (equip(player, piece)) {
actionBar(player, PvpLoader.getDonDone().replace("{piece}", pieceName(piece.type())));
player.playSound(player.getLocation(), Sound.ITEM_ARMOR_EQUIP_GENERIC, 1f, 1f);
Expand Down Expand Up @@ -510,7 +421,6 @@ private static boolean isEmpty(ItemStack item) {

static void clear() {
donning.clear();
equippedAt.clear();
completing.clear();
ticker = null;
}
Expand Down
49 changes: 1 addition & 48 deletions src/main/java/net/tfminecraft/rpcharacters/pvp/PvpCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;

import net.tfminecraft.tlibs.armour.ArmorEquipEvent;

import net.tfminecraft.rpcharacters.identity.DisplayIdentityService;
import net.tfminecraft.rpcharacters.loaders.PvpLoader;
import net.tfminecraft.rpcharacters.managers.PlayerManager;
import net.tfminecraft.rpcharacters.objects.PlayerData;
Expand Down Expand Up @@ -114,8 +111,7 @@ private void startWarning(Player player) {
if (previous != null) {
finish(previous);
}
takeOffRecentArmour(targets);
PvpSituation situation = new PvpSituation(player.getUniqueId(), targets, armoured(targets));
PvpSituation situation = new PvpSituation(player.getUniqueId(), targets);
PvpSituations.track(situation);
tasksBySituation.put(situation, new ArrayList<>());

Expand Down Expand Up @@ -230,49 +226,6 @@ private void schedule(PvpSituation situation, BukkitTask task) {
tasks.add(task);
}

/**
* Everyone caught in an open fight keeps the armour they had when it was called.
* Those in body armour may still put a helmet on.
*/
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onArmorEquip(ArmorEquipEvent event) {
Player player = event.getPlayer();
if (player == null || event.getNewArmorPiece() == null
|| !PvpSituations.locksArmour(player.getUniqueId(), event.getType())) {
return;
}
event.setCancelled(true);
RPTexts.send(player, PvpLoader.getArmourLocked());
}

/** Armour put on just before the fight was called hadn't been fastened yet. */
private void takeOffRecentArmour(List<UUID> targets) {
long now = System.currentTimeMillis();
for (UUID id : targets) {
Player online = Bukkit.getPlayer(id);
if (online == null || !ArmourDonning.takeOffRecent(online, now)) {
continue;
}
String notice = PvpLoader.getArmourStrippedOthers()
.replace("{name}", DisplayIdentityService.resolveDisplay(online));
List<UUID> others = new ArrayList<>(targets);
others.remove(id);
broadcast(others, notice);
}
}

/** Who is still in a chestplate, leggings and boots once recent armour is off. */
private static List<UUID> armoured(List<UUID> targets) {
List<UUID> armoured = new ArrayList<>();
for (UUID id : targets) {
Player online = Bukkit.getPlayer(id);
if (online != null && ArmourDonning.wearsBodyArmour(online)) {
armoured.add(id);
}
}
return armoured;
}

private void broadcast(List<UUID> targets, String raw) {
for (UUID id : targets) {
Player online = Bukkit.getPlayer(id);
Expand Down
12 changes: 0 additions & 12 deletions src/main/java/net/tfminecraft/rpcharacters/pvp/PvpSituation.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,13 @@ public final class PvpSituation {

private final UUID issuerId;
private final Set<UUID> participants;
private final Set<UUID> armoured;
private final Set<UUID> died = ConcurrentHashMap.newKeySet();
private boolean open = true;
private boolean started;

public PvpSituation(UUID issuerId, Collection<UUID> participants) {
this(issuerId, participants, null);
}

/** {@code armoured} are the participants who wore body armour when it was called. */
public PvpSituation(UUID issuerId, Collection<UUID> participants, Collection<UUID> armoured) {
this.issuerId = issuerId;
this.participants = idsOf(participants);
this.armoured = idsOf(armoured);
}

private static Set<UUID> idsOf(Collection<UUID> source) {
Expand Down Expand Up @@ -64,11 +57,6 @@ public boolean includes(UUID playerId) {
return playerId != null && participants.contains(playerId);
}

/** Came into the fight in a chestplate, leggings and boots, so may put a helmet on during it. */
public boolean wasArmoured(UUID playerId) {
return playerId != null && armoured.contains(playerId);
}

public boolean hasDied(UUID playerId) {
return playerId != null && died.contains(playerId);
}
Expand Down
19 changes: 0 additions & 19 deletions src/main/java/net/tfminecraft/rpcharacters/pvp/PvpSituations.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;

import net.tfminecraft.tlibs.armour.ArmorType;

/** Open {@code /pvp start} situations. The command layer owns timers and titles. */
public final class PvpSituations {

Expand Down Expand Up @@ -44,23 +42,6 @@ public static void markDeath(UUID playerId) {
}
}

/**
* From {@code /pvp start} until the fight closes, nobody in it who is still alive
* may put armour on. Helmets are free for those who came in wearing body armour.
*/
public static boolean locksArmour(UUID playerId, ArmorType type) {
if (playerId == null) {
return false;
}
for (PvpSituation situation : open) {
if (situation.isOpen() && situation.includes(playerId) && !situation.hasDied(playerId)
&& (type != ArmorType.HELMET || !situation.wasArmoured(playerId))) {
return true;
}
}
return false;
}

/** Caught in an open fight, from the warning until it closes, unless they died in it. */
public static boolean involves(UUID playerId) {
for (PvpSituation situation : open) {
Expand Down
Loading
Loading