This commit is contained in:
rattatwinko
2025-05-01 14:48:50 +02:00
commit ed944e0d76
4 changed files with 435 additions and 0 deletions

113
.gitignore vendored Normal file
View File

@@ -0,0 +1,113 @@
# User-specific stuff
.idea/
*.iml
*.ipr
*.iws
# IntelliJ
out/
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.jar
.flattened-pom.xml
# Common working directory
run/

87
pom.xml Normal file
View File

@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.AutoBow</groupId>
<artifactId>AutoBow</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>AutoBow</name>
<properties>
<java.version>21</java.version>
<kotlin.version>2.2.0-Beta2</kotlin.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<defaultGoal>clean package</defaultGoal>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<jvmTarget>${java.version}</jvmTarget>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<repositories>
<repository>
<id>papermc-repo</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.21.5-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,220 @@
package org.AutoBow.autoBow
import org.bukkit.Bukkit
import org.bukkit.ChatColor
import org.bukkit.Material
import org.bukkit.NamespacedKey
import org.bukkit.Registry
import org.bukkit.Sound
import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
import org.bukkit.entity.Arrow
import org.bukkit.entity.Entity
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.entity.EntityShootBowEvent
import org.bukkit.event.entity.ProjectileHitEvent
import org.bukkit.inventory.ItemFlag
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ItemMeta
import org.bukkit.plugin.java.JavaPlugin
import org.bukkit.scheduler.BukkitRunnable
import org.bukkit.util.Vector
import java.util.*
class AutoBow : JavaPlugin(), Listener {
companion object {
private const val POWER_LEVEL = 10
private const val AUTO_AIM_DISTANCE = 100.0 // Maximum distance for auto-aim
private const val KNOCKBACK_MULTIPLIER = 5.0
}
override fun onEnable() {
logger.info("AutoBow plugin has been enabled!")
server.pluginManager.registerEvents(this, this)
getCommand("autobow")?.setExecutor(AutoBowCommand())
// Register for arrow hit events to handle knockback
server.pluginManager.registerEvents(object : Listener {
@EventHandler
fun onProjectileHit(event: ProjectileHitEvent) {
val arrow = event.entity
if (arrow is Arrow && arrow.scoreboardTags.contains("autobow-knockback")) {
// Apply knockback if our arrow hit an entity
val hitEntity = event.hitEntity
if (hitEntity is Player) {
// Play XP sound on hit
arrow.world.playSound(arrow.location, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0f, 0.5f)
// Apply custom knockback
val direction = arrow.velocity.normalize().multiply(KNOCKBACK_MULTIPLIER)
hitEntity.velocity = hitEntity.velocity.add(direction)
// Additional effects
hitEntity.world.playSound(hitEntity.location, Sound.ENTITY_PLAYER_ATTACK_KNOCKBACK, 1.0f, 0.5f)
}
}
}
}, this)
}
override fun onDisable() {
logger.info("AutoBow plugin has been disabled!")
}
private inner class AutoBowCommand : CommandExecutor {
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<String>): Boolean {
if (sender !is Player) {
sender.sendMessage("${ChatColor.RED}This command can only be used by players!")
return true
}
val player = sender
// Check if player is op
if (!player.isOp) {
player.sendMessage("${ChatColor.RED}You don't have permission to use this command!")
return true
}
// Create the auto bow
val autoBow = createAutoBow()
// Give the player the bow
player.inventory.addItem(autoBow)
player.sendMessage("${ChatColor.GREEN}You have received the ${ChatColor.GOLD}Auto Bow${ChatColor.GREEN}! It will auto-aim at the nearest player.")
// Also give arrows if player doesn't have any
if (!player.inventory.contains(Material.ARROW)) {
player.inventory.addItem(ItemStack(Material.ARROW, 64))
player.sendMessage("${ChatColor.GREEN}You have received some arrows!")
}
return true
}
}
private fun createAutoBow(): ItemStack {
val bow = ItemStack(Material.BOW)
val meta = bow.itemMeta ?: return bow
// Set display name and lore
meta.setDisplayName("${ChatColor.GOLD}${ChatColor.BOLD}Auto-Aim Bow")
val lore = ArrayList<String>()
lore.add("${ChatColor.GRAY}This bow automatically aims at the nearest player.")
lore.add("${ChatColor.RED}Extreme Knockback")
lore.add("${ChatColor.RED}Power")
lore.add("${ChatColor.DARK_PURPLE}OP Only Weapon")
meta.lore = lore
// Add generic enchantment level appearance
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS)
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES)
// Set the item to be unbreakable
meta.isUnbreakable = true
bow.itemMeta = meta
// Enchant the bow - FIXED LINES (122-124)
val powerEnchant = Registry.ENCHANTMENT.get(NamespacedKey.minecraft("power"))
val infinityEnchant = Registry.ENCHANTMENT.get(NamespacedKey.minecraft("infinity"))
val unbreakingEnchant = Registry.ENCHANTMENT.get(NamespacedKey.minecraft("unbreaking"))
val knockbackEnchant = Registry.ENCHANTMENT.get(NamespacedKey.minecraft("knockback"))
if (powerEnchant != null) bow.addUnsafeEnchantment(powerEnchant, POWER_LEVEL)
if (infinityEnchant != null) bow.addUnsafeEnchantment(infinityEnchant, 1)
if (unbreakingEnchant != null) bow.addUnsafeEnchantment(unbreakingEnchant, 10)
if (knockbackEnchant != null) bow.addUnsafeEnchantment(knockbackEnchant, 10)
return bow
}
@EventHandler
fun onBowShoot(event: EntityShootBowEvent) {
if (event.entity !is Player) {
return
}
val shooter = event.entity as Player
val bow = event.bow ?: return
// Check if it's our special bow
if (bow.hasItemMeta() && bow.itemMeta?.hasDisplayName() == true &&
bow.itemMeta?.displayName == "${ChatColor.GOLD}${ChatColor.BOLD}Auto-Aim Bow") {
// Cancel the original arrow
event.isCancelled = true
// Find the nearest player
val nearestPlayer = Bukkit.getOnlinePlayers()
.filter { it != shooter }
.minByOrNull { it.location.distanceSquared(shooter.location) }
if (nearestPlayer != null) {
val distance = shooter.location.distance(nearestPlayer.location)
// Only auto-aim if within range
if (distance <= AUTO_AIM_DISTANCE) {
// Calculate the vector from the shooter to the target, accounting for movement and gravity
val direction = calculateInterceptVector(shooter, nearestPlayer)
// Spawn a new arrow with the calculated direction
val arrow = shooter.launchProjectile(Arrow::class.java, direction)
arrow.velocity = direction.multiply(2.0) // Increase arrow speed
arrow.isCritical = true
arrow.fireTicks = 100 // Set arrow on fire for visual effect
// Tag our arrow for custom knockback
arrow.addScoreboardTag("autobow-knockback")
// Set shooter as the arrow's shooter for proper damage attribution
arrow.shooter = shooter
// Play sound for feedback
shooter.playSound(shooter.location, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0f, 1.0f)
shooter.sendMessage("${ChatColor.GREEN}Auto-aiming at ${ChatColor.RED}${nearestPlayer.name}${ChatColor.GREEN} (${Math.round(distance)} blocks away)")
} else {
shooter.sendMessage("${ChatColor.RED}No players within range for auto-aim!")
// Fire a normal arrow if no valid targets
val arrow = shooter.launchProjectile(Arrow::class.java)
arrow.velocity = shooter.location.direction.multiply(2.0)
arrow.isCritical = true
arrow.addScoreboardTag("autobow-knockback")
}
} else {
shooter.sendMessage("${ChatColor.RED}No players to auto-aim at!")
// Fire a normal arrow if no valid targets
val arrow = shooter.launchProjectile(Arrow::class.java)
arrow.velocity = shooter.location.direction.multiply(2.0)
arrow.isCritical = true
arrow.addScoreboardTag("autobow-knockback")
}
}
}
private fun calculateInterceptVector(shooter: Player, target: Player): Vector {
// Get positions
val shooterPos = shooter.location.toVector()
val targetPos = target.location.toVector().add(Vector(0, 1, 0)) // Aim for center mass
// Get target velocity
val targetVel = target.velocity
// Calculate direction vector
val direction = targetPos.subtract(shooterPos)
// Add a small prediction based on target movement
direction.add(targetVel.multiply(5))
// Normalize and scale
return direction.normalize()
}
}

View File

@@ -0,0 +1,15 @@
name: AutoBow
version: 1.0-SNAPSHOT
main: org.AutoBow.autoBow.AutoBow
api-version: 1.18
description: Gives OP players an auto-aiming bow with knockback
commands:
autobow:
description: Gives you an auto-aiming bow with extreme knockback
usage: /autobow
permission: autobow.use
permission-message: You must be an operator to use this command!
permissions:
autobow.use:
description: Allows use of the AutoBow command
default: op