Merge pull request #88 from Protonull/elytra-features
Expand upon ElytraFeatures
This commit is contained in:
4 files changed
+290
-71
No files matched your search
+103
@@ -0,0 +1,103 @@
|
||||
package com.programmerdan.minecraft.simpleadminhacks.configs;
|
||||
|
||||
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
|
||||
import com.programmerdan.minecraft.simpleadminhacks.framework.SimpleHackConfig;
|
||||
import javax.annotation.Nonnull;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import vg.civcraft.mc.civmodcore.util.CivLogger;
|
||||
|
||||
public final class ElytraFeaturesConfig extends SimpleHackConfig {
|
||||
private final CivLogger logger;
|
||||
|
||||
private boolean disableFlight;
|
||||
private boolean disableFlightInCombat;
|
||||
|
||||
private boolean disableFireworkBoosting;
|
||||
private boolean disableFireworkBoostingInCombat;
|
||||
private boolean disableSafeFireworkBoosting;
|
||||
|
||||
private int heightDamage;
|
||||
private double heightDamageScaling;
|
||||
private int heightBuffer;
|
||||
private long heightDamageInterval;
|
||||
|
||||
public ElytraFeaturesConfig(@Nonnull final SimpleAdminHacks plugin,
|
||||
@Nonnull final ConfigurationSection base) {
|
||||
super(plugin, base, false);
|
||||
this.logger = CivLogger.getLogger(getClass());
|
||||
wireup(base);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void wireup(@Nonnull final ConfigurationSection config) {
|
||||
this.disableFlight = config.getBoolean("disableFlight", false);
|
||||
|
||||
this.disableFlightInCombat = config.getBoolean("disableFlightInCombat", false);
|
||||
|
||||
this.disableFireworkBoosting = config.getBoolean("disableFireworkBoosting", false);
|
||||
|
||||
this.disableFireworkBoostingInCombat = config.getBoolean("disableFireworkBoostingInCombat", false);
|
||||
|
||||
this.disableSafeFireworkBoosting = config.getBoolean("disableSafeFireworkBoosting", false);
|
||||
|
||||
this.heightDamage = config.getInt("heightDamage.damage", 1);
|
||||
if (this.heightDamage < 0) {
|
||||
this.logger.warning("[heightDamage.damage] was set to [" + this.heightDamage + "], " +
|
||||
"which is invalid, defaulting to: 1");
|
||||
this.heightDamage = 1;
|
||||
}
|
||||
|
||||
this.heightDamageScaling = config.getDouble("heightDamage.scales", 1d);
|
||||
if (this.heightDamageScaling <= 0d) {
|
||||
this.logger.warning("[heightDamage.scales] was set to [" + this.heightDamageScaling + "], " +
|
||||
"which is invalid, defaulting to: 1.0d");
|
||||
this.heightDamageScaling = 1d;
|
||||
}
|
||||
|
||||
this.heightBuffer = config.getInt("heightDamage.buffer", 5);
|
||||
|
||||
this.heightDamageInterval = config.getLong("heightDamage.interval", 1000L);
|
||||
if (this.heightDamageInterval < 1L) {
|
||||
this.logger.warning("[heightDamage.interval] was set to [" + this.heightDamageInterval + "], " +
|
||||
"which is invalid, defaulting to: 1000L");
|
||||
this.heightDamageInterval = 1000L;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFlightDisabled() {
|
||||
return this.disableFlight;
|
||||
}
|
||||
|
||||
public boolean isFlightDisabledInCombat() {
|
||||
return this.disableFlightInCombat;
|
||||
}
|
||||
|
||||
public boolean isBoostingDisabled() {
|
||||
return this.disableFireworkBoosting;
|
||||
}
|
||||
|
||||
public boolean isBoostingDisabledInCombat() {
|
||||
return this.disableFireworkBoostingInCombat;
|
||||
}
|
||||
|
||||
public boolean isSafeBoostingDisabled() {
|
||||
return this.disableSafeFireworkBoosting;
|
||||
}
|
||||
|
||||
public int getHeightDamage() {
|
||||
return this.heightDamage;
|
||||
}
|
||||
|
||||
public double isHeightDamageScaling() {
|
||||
return this.heightDamageScaling;
|
||||
}
|
||||
|
||||
public int getHeightBuffer() {
|
||||
return this.heightBuffer;
|
||||
}
|
||||
|
||||
public long getHeightDamageInterval() {
|
||||
return this.heightDamageInterval;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
package com.programmerdan.minecraft.simpleadminhacks.hacks;
|
||||
|
||||
import com.destroystokyo.paper.event.player.PlayerElytraBoostEvent;
|
||||
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
|
||||
import com.programmerdan.minecraft.simpleadminhacks.configs.ElytraFeaturesConfig;
|
||||
import com.programmerdan.minecraft.simpleadminhacks.framework.SimpleHack;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
import java.util.Comparator;
|
||||
import javax.annotation.Nonnull;
|
||||
import net.minelink.ctplus.CombatTagPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityToggleGlideEvent;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
public final class ElytraFeatures extends SimpleHack<ElytraFeaturesConfig> implements Listener {
|
||||
|
||||
public ElytraFeatures(@Nonnull final SimpleAdminHacks plugin,
|
||||
@Nonnull final ElytraFeaturesConfig config) {
|
||||
super(plugin, config);
|
||||
}
|
||||
|
||||
public static ElytraFeaturesConfig generate(@Nonnull final SimpleAdminHacks plugin,
|
||||
@Nonnull final ConfigurationSection config) {
|
||||
return new ElytraFeaturesConfig(plugin, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
plugin().registerListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
|
||||
private boolean INTERNAL_hasBypassPermission(final Entity entity) {
|
||||
return entity instanceof Player && entity.hasPermission("simpleadmin.elytrabypass");
|
||||
}
|
||||
|
||||
private boolean INTERNAL_isInCombat(final Entity entity) {
|
||||
if (!(entity instanceof Player)) {
|
||||
return false;
|
||||
}
|
||||
final PluginManager pluginManager = Bukkit.getPluginManager();
|
||||
final Plugin foundPlugin = pluginManager.getPlugin("CombatTagPlus");
|
||||
if (pluginManager.isPluginEnabled(foundPlugin)) {
|
||||
final CombatTagPlus combatTagPlugin = (CombatTagPlus) foundPlugin;
|
||||
return combatTagPlugin.getTagManager().isTagged(entity.getUniqueId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Elytra flight
|
||||
// ------------------------------------------------------------
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void regulateElytraFlight(@Nonnull final EntityToggleGlideEvent event) {
|
||||
boolean disableFlight = false;
|
||||
if (config().isFlightDisabled()) {
|
||||
disableFlight = true;
|
||||
}
|
||||
else {
|
||||
if (config().isFlightDisabledInCombat()) {
|
||||
disableFlight = INTERNAL_isInCombat(event.getEntity());
|
||||
}
|
||||
}
|
||||
if (disableFlight) {
|
||||
if (!INTERNAL_hasBypassPermission(event.getEntity())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Elytra boosting
|
||||
// ------------------------------------------------------------
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void regulateElytraBoosting(@Nonnull final PlayerElytraBoostEvent event) {
|
||||
boolean disableBoosting = false;
|
||||
if (config().isBoostingDisabled()) {
|
||||
disableBoosting = true;
|
||||
}
|
||||
else {
|
||||
if (config().isBoostingDisabledInCombat()) {
|
||||
if (INTERNAL_isInCombat(event.getPlayer())) {
|
||||
disableBoosting = true;
|
||||
}
|
||||
}
|
||||
if (config().isSafeBoostingDisabled()) {
|
||||
if (!event.getFirework().getFireworkMeta().hasEffects()) {
|
||||
disableBoosting = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (disableBoosting) {
|
||||
if (!INTERNAL_hasBypassPermission(event.getPlayer())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Elytra damage
|
||||
// ------------------------------------------------------------
|
||||
|
||||
private static final class ElytraDamage {
|
||||
private long lastDamageTime;
|
||||
private double damageToDeal;
|
||||
}
|
||||
|
||||
private final Object2ObjectMap<Player, ElytraDamage> damageElytraFlightTracker =
|
||||
new Object2ObjectAVLTreeMap<>(Comparator.comparing(Player::getUniqueId));
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void damageFliersAboveWorldHeight(final PlayerMoveEvent event) {
|
||||
if (config().getHeightDamage() <= 0) {
|
||||
return;
|
||||
}
|
||||
final Player player = event.getPlayer();
|
||||
if (!player.isGliding() || INTERNAL_hasBypassPermission(player)) {
|
||||
return;
|
||||
}
|
||||
final Location fromLocation = event.getFrom();
|
||||
final int allowedHeight = fromLocation.getWorld().getMaxHeight() + config().getHeightBuffer();
|
||||
final int blocksAboveAllowedHeight = fromLocation.getBlockY() - allowedHeight;
|
||||
// If the player is within the allowed height, do nothing
|
||||
if (blocksAboveAllowedHeight <= 0) {
|
||||
return;
|
||||
}
|
||||
final ElytraDamage details = this.damageElytraFlightTracker.computeIfAbsent(
|
||||
player, (_key) -> new ElytraDamage());
|
||||
details.damageToDeal = Math.max(details.damageToDeal,
|
||||
config().getHeightDamage() * blocksAboveAllowedHeight * config().isHeightDamageScaling());
|
||||
final long now = System.currentTimeMillis();
|
||||
final long deltaInterval = now - details.lastDamageTime;
|
||||
// If it's not the right time to damage the player, do nothing
|
||||
if (deltaInterval < config().getHeightDamageInterval()) {
|
||||
return;
|
||||
}
|
||||
player.damage(details.damageToDeal);
|
||||
details.damageToDeal = 0;
|
||||
details.lastDamageTime = now;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void resetDamageElytraFlightOnLogout(final PlayerQuitEvent event) {
|
||||
this.damageElytraFlightTracker.remove(event.getPlayer());
|
||||
}
|
||||
|
||||
}
|
||||
-66
@@ -1,66 +0,0 @@
|
||||
package com.programmerdan.minecraft.simpleadminhacks.hacks.basic;
|
||||
|
||||
import com.destroystokyo.paper.event.player.PlayerElytraBoostEvent;
|
||||
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
|
||||
import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHack;
|
||||
import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHackConfig;
|
||||
import com.programmerdan.minecraft.simpleadminhacks.framework.autoload.AutoLoad;
|
||||
import net.minelink.ctplus.CombatTagPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityToggleGlideEvent;
|
||||
|
||||
public class ElytraFeatures extends BasicHack {
|
||||
|
||||
@AutoLoad
|
||||
private boolean disableFlight;
|
||||
|
||||
@AutoLoad
|
||||
private boolean disableFireworkBoosting;
|
||||
|
||||
@AutoLoad
|
||||
private boolean disableFlightInCombat;
|
||||
|
||||
public ElytraFeatures(final SimpleAdminHacks plugin, final BasicHackConfig config) {
|
||||
super(plugin, config);
|
||||
}
|
||||
|
||||
private boolean hasBypassPermission(final Entity entity) {
|
||||
if (!(entity instanceof Player)) {
|
||||
return false;
|
||||
}
|
||||
return entity.hasPermission("simpleadmin.elytrabypass");
|
||||
}
|
||||
|
||||
private boolean isInCombat(final Entity entity) {
|
||||
if (!(entity instanceof Player)) {
|
||||
return false;
|
||||
}
|
||||
final var pluginManager = Bukkit.getPluginManager();
|
||||
final var foundPlugin = pluginManager.getPlugin("CombatTagPlus");
|
||||
if (pluginManager.isPluginEnabled(foundPlugin)) {
|
||||
final var combatTagPlugin = (CombatTagPlus) foundPlugin;
|
||||
return combatTagPlugin.getTagManager().isTagged(entity.getUniqueId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void disableElytraFlight(final EntityToggleGlideEvent event) {
|
||||
if (this.disableFlight || (this.disableFlightInCombat && isInCombat(event.getEntity()))) {
|
||||
if (!hasBypassPermission(event.getEntity())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void disableElytraFireworkBoosting(final PlayerElytraBoostEvent event) {
|
||||
if (this.disableFireworkBoosting && !hasBypassPermission(event.getPlayer())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -92,11 +92,6 @@ hacks:
|
||||
announcements:
|
||||
- "[\"\",{\"text\":\"Buy \"},{\"text\":\"Dogecoin\",\"color\":\"dark_red\",\"clickEvent\":{\"action\":\"open_url\",\"value\":\"https://www.coindesk.com/price/dogecoin\"}},{\"text\":\"!\"}]"
|
||||
- "[\"\",{\"text\":\"Very \"},{\"text\":\"Wow!\",\"italic\":true,\"hoverEvent\":{\"action\":\"show_text\",\"contents\":\"Wow!\"}}]"
|
||||
ElytraFeatures:
|
||||
enabled: true
|
||||
disableFlight: false
|
||||
disableFireworkBoosting: false
|
||||
disableFlightInCombat: false
|
||||
EventDebugHack:
|
||||
enabled: true
|
||||
EventHandlerList:
|
||||
@@ -242,6 +237,29 @@ hacks:
|
||||
# Note: You can also just state "ALL" for all spawn circumstances
|
||||
VILLAGER: ALL
|
||||
ENDERMITE: [DISPENSE_EGG, EGG, SPAWNER_EGG]
|
||||
ElytraFeatures:
|
||||
enabled: true
|
||||
# Whether Elytra flight should be outright disabled
|
||||
disableFlight: false
|
||||
# Whether Elytra flight should be disabled in combat
|
||||
disableFlightInCombat: false
|
||||
# Whether firework boosting should be outright disabled
|
||||
disableFireworkBoosting: false
|
||||
# Whether firework boosting should be disabled in combat
|
||||
disableFireworkBoostingInCombat: false
|
||||
# Whether to restrict firework boosting to explosive fireworks
|
||||
disableSafeFireworkBoosting: false
|
||||
# This regulates player damage when Elytra flying above world height.
|
||||
heightDamage:
|
||||
# The amount of damage (in half-hearts) the flier should take.
|
||||
# NOTE: Setting to 0 will disable the damage.
|
||||
damage: 1
|
||||
# The damage is multiplied by the number of blocks above world height multiplied by this number.
|
||||
scales: 1.0
|
||||
# The amount of blocks above height limit where damage is not applied.
|
||||
buffer: 5
|
||||
# The interval (in milliseconds) between damage ticks.
|
||||
interval: 1000
|
||||
Experimental:
|
||||
enabled: true
|
||||
combatspy: false
|
||||
|
||||
Reference in new issue
Block a user