diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 0000000..752bb1b --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,23 @@ +name: Gradle Build + +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/checkout@v4 + with: + repository: headhunter45/ScoreKeeper + path: ScoreKeeper + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '25' + - uses: gradle/actions/setup-gradle@v4 + - run: ./gradlew publishToMavenLocal + working-directory: ScoreKeeper + - run: ./gradlew test build \ No newline at end of file diff --git a/README.md b/README.md index 69d2cf5..523d381 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ ScoreTable: Restart the server after editing the configuration. A configured value of `0` suppresses that entity from the score table shown to players when they join. -MobScores has no commands of its own. Current killer attribution is recorded for zombie entities directly damaged by a player; projectile and other mob attribution are not currently handled. Points are awarded through ScoreKeeper's existing player API and follow the player's UUID-backed score. +MobScores has no commands of its own. It records credit for configured entity types damaged directly by a player or by a projectile fired by a player. Other mob attribution is not currently handled. Points are awarded through ScoreKeeper's existing player API and follow the player's UUID-backed score. ## Build diff --git a/TODO.md b/TODO.md index e18d937..90bfdfe 100644 --- a/TODO.md +++ b/TODO.md @@ -17,7 +17,7 @@ | MS-13 | Done | Build the plugin with Gradle (./gradlew build) and test on a modern Paper server using the provided bash scripts. | MS-14 | Done | Address any bugs or incompatibilities found during testing on a modern server. | MS-15 | Done | Update README.md and CONTRIBUTING.md with new build, usage, and development instructions. _(Depends on: bugfixes)_ -| MS-16 | Ready | (Optional) Add new features, quality-of-life improvements, automated tests, or CI configuration. _(Depends on: docs update)_ +| MS-16 | Done | (Optional) Add new features, quality-of-life improvements, automated tests, or CI configuration. _(Depends on: docs update)_ | MS-17 | Done | Update MobScores to depend on the latest version of the ScoreKeeper plugin (update dependency in build.gradle and plugin.yml as needed). | MS-18 | Ready | Test MobScores with the latest ScoreKeeper to ensure score tracking, awarding, and all integration points work as expected (including with players who have changed names). | MS-19 | Done | Refactor MobDeathListener and PlayerConnectListener to implement Listener interface and use @EventHandler annotations instead of extending EntityListener/PlayerListener. diff --git a/src/main/java/com/majinnaibu/minecraft/plugins/mobscores/MobScoresPlugin.java b/src/main/java/com/majinnaibu/minecraft/plugins/mobscores/MobScoresPlugin.java index 47bff12..f324795 100644 --- a/src/main/java/com/majinnaibu/minecraft/plugins/mobscores/MobScoresPlugin.java +++ b/src/main/java/com/majinnaibu/minecraft/plugins/mobscores/MobScoresPlugin.java @@ -18,7 +18,6 @@ along with MobScores. If not, see . package com.majinnaibu.minecraft.plugins.mobscores; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; import java.util.UUID; import java.util.logging.Level; @@ -29,7 +28,6 @@ import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; -import org.bukkit.entity.Zombie; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; @@ -58,12 +56,9 @@ public class MobScoresPlugin extends JavaPlugin { // Create the default config if it doesn't exist. saveDefaultConfig(); - getConfig().set("ScoreTable", serializeScoreTable(getDefaultScoreTable())); - saveConfig(); - // Load our score table from config or set defaults. if (getConfig().isConfigurationSection("ScoreTable")) { - deserializeScoreTable(getConfig().getConfigurationSection("ScoreTable").getValues(false)); + _scoreTable = deserializeScoreTable(getConfig().getConfigurationSection("ScoreTable").getValues(false)); } else { _scoreTable = getDefaultScoreTable(); getConfig().set("ScoreTable", serializeScoreTable(_scoreTable)); @@ -113,7 +108,7 @@ public class MobScoresPlugin extends JavaPlugin { } public void claimMob(Entity entity, Player damager) { - if(entity instanceof Zombie){ + if (_scoreTable.containsKey(entity.getType())) { _claimedMobs.put(entity.getUniqueId(), damager.getUniqueId()); } } @@ -137,14 +132,12 @@ public class MobScoresPlugin extends JavaPlugin { } public void sendPlayerScoreTable(Player player) { - Iterator> i = _scoreTable.entrySet().iterator(); - Map.Entry pair = null; - for(pair = i.next(); i.hasNext(); pair = i.next()){ - if(pair.getValue() != 0){ - EntityType type = pair.getKey(); + for (Map.Entry entry : _scoreTable.entrySet()) { + if (entry.getValue() != 0) { + EntityType type = entry.getKey(); Component message = Component.translatable(type.translationKey()) .append(Component.text(" = ")) - .append(Component.text(String.valueOf(pair.getValue())) + .append(Component.text(String.valueOf(entry.getValue())) .color(NamedTextColor.GREEN)); sendPlayerMessage(player, message); } diff --git a/src/main/java/com/majinnaibu/minecraft/plugins/mobscores/listeners/MobDeathListener.java b/src/main/java/com/majinnaibu/minecraft/plugins/mobscores/listeners/MobDeathListener.java index 6779a84..ea3fed0 100644 --- a/src/main/java/com/majinnaibu/minecraft/plugins/mobscores/listeners/MobDeathListener.java +++ b/src/main/java/com/majinnaibu/minecraft/plugins/mobscores/listeners/MobDeathListener.java @@ -19,6 +19,7 @@ package com.majinnaibu.minecraft.plugins.mobscores.listeners; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDeathEvent; @@ -37,12 +38,19 @@ public class MobDeathListener implements Listener { @EventHandler public void onEntityDamage(EntityDamageEvent event) { - if(event instanceof EntityDamageByEntityEvent){ - EntityDamageByEntityEvent ev = (EntityDamageByEntityEvent) event; - Entity damager = ev.getDamager(); - if(damager instanceof Player){ - _plugin.claimMob(ev.getEntity(), (Player)damager); - } + if (!(event instanceof EntityDamageByEntityEvent damageEvent)) { + return; + } + Entity damager = damageEvent.getDamager(); + Player creditedPlayer = null; + if (damager instanceof Player directPlayer) { + creditedPlayer = directPlayer; + } else if (damager instanceof Projectile projectile + && projectile.getShooter() instanceof Player projectileShooter) { + creditedPlayer = projectileShooter; + } + if (creditedPlayer != null) { + _plugin.claimMob(event.getEntity(), creditedPlayer); } }