Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85a2070f4a
|
||
|
|
ab1365b738
|
||
|
|
d5a72a1900 | ||
|
|
0a02f9b5d3 | ||
|
|
aa9dd8a4e3 | ||
|
|
209d53e975 | ||
|
|
e2f5d5692c | ||
|
|
5337604dc0 |
No files matched your search
@@ -0,0 +1 @@
|
||||
.gitea/CODEOWNERS linguist-detectable=false
|
||||
@@ -0,0 +1,3 @@
|
||||
# Pull requests request review from the eligible staff team(s).
|
||||
# One approval from either an Admin or Developer satisfies branch protection.
|
||||
* @trueog/Admins @trueog/Developers
|
||||
@@ -10,6 +10,8 @@ PurpurExtras is a plugin designed to add all [Purpur](https://github.com/PurpurM
|
||||
|
||||
- Lobotomized CreateSusBlockModule.
|
||||
|
||||
- Removed OpenIronDoorsWithHandModule (also applies to trapdoors).
|
||||
|
||||
- Added more error handling.
|
||||
|
||||
## Contact
|
||||
@@ -20,4 +22,4 @@ Join us on [Discord](https://discord.gg/ma9pMYpBU6)
|
||||
|
||||
[](LICENSE)
|
||||
|
||||
All code is licensed under the GPL-2.0 license, unless otherwise noted.
|
||||
All code is licensed under the GPL-2.0 license, unless otherwise noted.
|
||||
@@ -0,0 +1,125 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import org.bukkit.EntityEffect;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* If enabled, a totem of undying will save a player from death while it sits
|
||||
* anywhere in their hotbar, not only when held in the main hand or off hand.
|
||||
* Vanilla resurrection (totem in either hand) is left untouched; this module
|
||||
* only covers the remaining hotbar slots. Void deaths are intentionally ignored
|
||||
* because surviving them requires the teleport handled by
|
||||
* {@link VoidTotemModule}.
|
||||
*/
|
||||
public class HotbarTotemModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final Collection<PotionEffect> totemEffects = new ArrayList<>();
|
||||
|
||||
protected HotbarTotemModule() {
|
||||
|
||||
totemEffects.add(new PotionEffect(PotionEffectType.REGENERATION, 20 * 45, 1));
|
||||
totemEffects.add(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 20 * 40, 0));
|
||||
totemEffects.add(new PotionEffect(PotionEffectType.ABSORPTION, 20 * 5, 1));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.totem.work-from-hotbar", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onLethalDamage(EntityDamageEvent event) {
|
||||
|
||||
if (!(event.getEntity() instanceof Player player))
|
||||
return;
|
||||
// Void deaths are handled by VoidTotemModule, which teleports the player to
|
||||
// safety.
|
||||
if (event.getCause().equals(EntityDamageEvent.DamageCause.VOID))
|
||||
return;
|
||||
// Damage is survivable, let it through unchanged.
|
||||
if (player.getHealth() - event.getFinalDamage() > 0)
|
||||
return;
|
||||
|
||||
PlayerInventory inventory = player.getInventory();
|
||||
// Vanilla already resurrects when a totem is held in either hand.
|
||||
if (inventory.getItemInMainHand().getType().equals(Material.TOTEM_OF_UNDYING)
|
||||
|| inventory.getItemInOffHand().getType().equals(Material.TOTEM_OF_UNDYING))
|
||||
return;
|
||||
|
||||
int slot = findHotbarTotemSlot(inventory);
|
||||
if (slot < 0)
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
consumeTotem(inventory, slot);
|
||||
applyTotemEffects(player);
|
||||
|
||||
}
|
||||
|
||||
private int findHotbarTotemSlot(PlayerInventory inventory) {
|
||||
|
||||
for (int slot = 0; slot <= 8; slot++) {
|
||||
|
||||
ItemStack item = inventory.getItem(slot);
|
||||
if (item != null && item.getType().equals(Material.TOTEM_OF_UNDYING))
|
||||
return slot;
|
||||
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
private void consumeTotem(PlayerInventory inventory, int slot) {
|
||||
|
||||
ItemStack totem = inventory.getItem(slot);
|
||||
if (totem == null)
|
||||
return;
|
||||
int remaining = totem.getAmount() - 1;
|
||||
if (remaining <= 0) {
|
||||
|
||||
inventory.setItem(slot, null);
|
||||
|
||||
} else {
|
||||
|
||||
totem.setAmount(remaining);
|
||||
inventory.setItem(slot, totem);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void applyTotemEffects(Player player) {
|
||||
|
||||
player.setFallDistance(0);
|
||||
player.setHealth(1);
|
||||
player.playEffect(EntityEffect.TOTEM_RESURRECT);
|
||||
player.getActivePotionEffects().forEach(potionEffect -> player.removePotionEffect(potionEffect.getType()));
|
||||
player.addPotionEffects(this.totemEffects);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.SoundCategory;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.Openable;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.util.permissions.DefaultPermissions;
|
||||
import org.purpurmc.purpurextras.PurpurConfig;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* Allows opening iron doors and trapdoors with a hand, just like wooden doors.
|
||||
*/
|
||||
public class OpenIronDoorsWithHandModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final boolean doors, trapdoors;
|
||||
private final String openIronDoorsPermission = "purpurextras.openirondoors";
|
||||
private final String openIronTrapdoorsPermission = "purpurextras.openirontrapdoors";
|
||||
|
||||
protected OpenIronDoorsWithHandModule() {
|
||||
|
||||
PurpurConfig config = PurpurExtrasOG.getPurpurConfig();
|
||||
doors = config.getBoolean("settings.gameplay-settings.open-iron-doors-with-hand", false);
|
||||
trapdoors = config.getBoolean("settings.gameplay-settings.open-iron-trapdoors-with-hand", false);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
DefaultPermissions.registerPermission(openIronDoorsPermission, "Allows for opening iron doors with a hand",
|
||||
PermissionDefault.TRUE);
|
||||
DefaultPermissions.registerPermission(openIronTrapdoorsPermission,
|
||||
"Allows for opening iron trapdoors with a hand", PermissionDefault.TRUE);
|
||||
return doors || trapdoors;
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onIronDoorOpen(PlayerInteractEvent event) {
|
||||
|
||||
if (!EquipmentSlot.HAND.equals(event.getHand()))
|
||||
return;
|
||||
if (event.getPlayer().isSneaking())
|
||||
return;
|
||||
if (!event.getAction().isRightClick())
|
||||
return;
|
||||
if (event.getClickedBlock() == null)
|
||||
return;
|
||||
Block block = event.getClickedBlock();
|
||||
World world = block.getWorld();
|
||||
switch (block.getType()) {
|
||||
|
||||
case IRON_DOOR -> {
|
||||
|
||||
if (!doors)
|
||||
return;
|
||||
if (!event.getPlayer().hasPermission(openIronDoorsPermission))
|
||||
return;
|
||||
event.setCancelled(true);
|
||||
if (open(block, event.getPlayer())) {
|
||||
|
||||
world.playSound(block.getLocation(), Sound.BLOCK_IRON_DOOR_OPEN, SoundCategory.BLOCKS, 1f, 1f);
|
||||
|
||||
} else {
|
||||
|
||||
world.playSound(block.getLocation(), Sound.BLOCK_IRON_DOOR_CLOSE, SoundCategory.BLOCKS, 1f, 1f);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
case IRON_TRAPDOOR -> {
|
||||
|
||||
if (!trapdoors)
|
||||
return;
|
||||
if (!event.getPlayer().hasPermission(openIronTrapdoorsPermission))
|
||||
return;
|
||||
event.setCancelled(true);
|
||||
if (open(block, event.getPlayer())) {
|
||||
|
||||
world.playSound(block.getLocation(), Sound.BLOCK_IRON_TRAPDOOR_OPEN, SoundCategory.BLOCKS, 1f, 1f);
|
||||
|
||||
} else {
|
||||
|
||||
world.playSound(block.getLocation(), Sound.BLOCK_IRON_TRAPDOOR_CLOSE, SoundCategory.BLOCKS, 1f, 1f);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
default -> throw new IllegalArgumentException(
|
||||
"Unexpected value in OpenIronDoorsWithHandModule: " + block.getType());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean open(Block block, Player player) {
|
||||
|
||||
Openable openable = (Openable) block.getBlockData();
|
||||
boolean isOpen = openable.isOpen();
|
||||
openable.setOpen(!isOpen);
|
||||
block.setBlockData(openable);
|
||||
player.swingMainHand();
|
||||
return !isOpen;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,11 +30,20 @@ public class ShieldSettingsModule implements PurpurExtrasModule, Listener {
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
if (shieldDamageReduction != DEFAULT_SHIELD_DAMAGE_REDUCTION) {
|
||||
// OldCombatMechanics owns shield reduction when present,
|
||||
// else both scale blocking and compound. Presence, not
|
||||
// enabled state, since OCM may enable after this module.
|
||||
boolean ocmOwnsShields = plugin.getServer().getPluginManager().getPlugin("OldCombatMechanics") != null;
|
||||
|
||||
if (shieldDamageReduction != DEFAULT_SHIELD_DAMAGE_REDUCTION && !ocmOwnsShields) {
|
||||
|
||||
plugin.getServer().getPluginManager()
|
||||
.registerEvents(new ShieldDamageReductionListener(shieldDamageReduction), plugin);
|
||||
|
||||
} else if (shieldDamageReduction != DEFAULT_SHIELD_DAMAGE_REDUCTION) {
|
||||
|
||||
plugin.getLogger().info("Skipping shield damage reduction: OldCombatMechanics owns it.");
|
||||
|
||||
}
|
||||
|
||||
if (shieldCooldown != DEFAULT_SHIELD_COOLDOWN) {
|
||||
|
||||
+9
-6
@@ -5,6 +5,7 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
|
||||
public class ShieldDamageReductionListener implements Listener {
|
||||
|
||||
@@ -24,14 +25,16 @@ public class ShieldDamageReductionListener implements Listener {
|
||||
if (!humanEntity.isBlocking())
|
||||
return;
|
||||
|
||||
double originalDamage = event.getDamage();
|
||||
double finalDamage = event.getFinalDamage();
|
||||
double reduction = originalDamage - finalDamage;
|
||||
// Scale only the blocking modifier. Writing a post-armour value
|
||||
// into BASE made armour and resistance apply a second time.
|
||||
if (!event.isApplicable(EntityDamageEvent.DamageModifier.BLOCKING))
|
||||
return;
|
||||
|
||||
double newReduction = shieldDamageReduction * reduction;
|
||||
double newDamage = finalDamage + newReduction;
|
||||
double blocking = event.getDamage(EntityDamageEvent.DamageModifier.BLOCKING);
|
||||
if (blocking == 0.0)
|
||||
return;
|
||||
|
||||
event.setDamage(newDamage);
|
||||
event.setDamage(EntityDamageEvent.DamageModifier.BLOCKING, blocking * shieldDamageReduction);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,6 @@ settings:
|
||||
pig: no
|
||||
enabled: false
|
||||
gameplay-settings:
|
||||
open-iron-doors-with-hand: false
|
||||
open-iron-trapdoors-with-hand: true
|
||||
respawn-anchor-needs-charges: true
|
||||
spawner-placement-requires-specific-permission: true
|
||||
run-faster-on-paths:
|
||||
@@ -56,6 +54,7 @@ settings:
|
||||
enabled: true
|
||||
totem:
|
||||
work-on-void-death: true
|
||||
work-from-hotbar: true
|
||||
blocks:
|
||||
shift-right-click-for-invisible-item-frames: false
|
||||
chorus-flowers-always-drop: true
|
||||
|
||||
Reference in new issue
Block a user