Fix Paper 26.2 explosion restoration stall
This commit is contained in:
@@ -0,0 +1,79 @@
|
|||||||
|
name: build
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
version: ${{ steps.version.outputs.version }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: 'Checkout'
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 'Set up JDK'
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
java-version: '25'
|
||||||
|
distribution: 'temurin'
|
||||||
|
cache: 'gradle'
|
||||||
|
|
||||||
|
- name: 'Build'
|
||||||
|
run: ./gradlew build --no-daemon
|
||||||
|
|
||||||
|
- name: 'Upload artifact'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: MobArena.jar
|
||||||
|
path: build/libs/MobArena-*.jar
|
||||||
|
|
||||||
|
- name: 'Output version'
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
version=$(
|
||||||
|
unzip -p build/libs/MobArena-*.jar plugin.yml \
|
||||||
|
| grep '^version: ' \
|
||||||
|
| awk '{printf $2}' \
|
||||||
|
| tr -d "'" \
|
||||||
|
)
|
||||||
|
echo "version=${version}" >> "${GITHUB_OUTPUT}"
|
||||||
|
|
||||||
|
draft:
|
||||||
|
needs: build
|
||||||
|
|
||||||
|
if: |
|
||||||
|
needs.build.result == 'success' &&
|
||||||
|
github.ref_name == 'master' &&
|
||||||
|
startsWith(github.event.head_commit.message, 'Release ') &&
|
||||||
|
!endsWith(needs.build.outputs.version, '-SNAPSHOT')
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
env:
|
||||||
|
VERSION: ${{ needs.build.outputs.version }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: 'Checkout'
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 'Download artifact'
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: MobArena.jar
|
||||||
|
|
||||||
|
- name: 'Extract release notes'
|
||||||
|
run: scripts/extract-release-notes -f github "${VERSION}" > release-notes.md
|
||||||
|
|
||||||
|
- name: 'Create release draft'
|
||||||
|
run: gh release create "${VERSION}" --draft --notes-file release-notes.md MobArena-*.jar
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
@@ -18,10 +18,10 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: 'Set up JDK'
|
- name: 'Set up JDK'
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: '11'
|
java-version: '25'
|
||||||
distribution: 'adopt'
|
distribution: 'temurin'
|
||||||
cache: 'gradle'
|
cache: 'gradle'
|
||||||
|
|
||||||
- name: 'Build'
|
- name: 'Build'
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
MobArena [](https://github.com/garbagemule/MobArena/actions/workflows/build.yml)
|
MobArena — Paper 26.2 fork
|
||||||
========
|
==========================
|
||||||
|
|
||||||
MobArena is an arena-style minigame for Spigot-based Minecraft servers
|
This fork updates upstream MobArena 0.109 for **Paper 26.2** and **Java 25**. It removes the legacy Bukkit material access that could stall the server during arena explosions and updates APIs renamed in modern Paper.
|
||||||
|
|
||||||
|
Upstream project: https://github.com/garbagemule/MobArena
|
||||||
|
|
||||||
|
Build with `./gradlew build`. The deployable plugin is written to `build/libs/MobArena-0.109.1-tss3.jar`.
|
||||||
|
|
||||||
|
MobArena is an arena-style minigame for Paper-based Minecraft servers.
|
||||||
|
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|||||||
+34
-6
@@ -1,31 +1,36 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("java-library")
|
id("java-library")
|
||||||
id("com.github.johnrengelman.shadow") version "8.1.1"
|
id("com.gradleup.shadow") version "9.6.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "com.garbagemule"
|
group = "com.garbagemule"
|
||||||
version = "0.109"
|
version = "0.109.1-tss3"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
|
maven("https://repo.papermc.io/repository/maven-public/")
|
||||||
maven("https://jitpack.io")
|
maven("https://jitpack.io")
|
||||||
maven("https://repo.maven.apache.org/maven2/")
|
maven("https://repo.maven.apache.org/maven2/")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly("org.spigotmc:spigot-api:1.19-R0.1-SNAPSHOT")
|
compileOnly("io.papermc.paper:paper-api:26.2.build.84-stable")
|
||||||
compileOnly("com.github.MilkBowl:VaultAPI:1.7.1")
|
compileOnly("com.github.MilkBowl:VaultAPI:1.7.1")
|
||||||
api("org.bstats:bstats-bukkit:2.2.1")
|
api("org.bstats:bstats-bukkit:2.2.1")
|
||||||
|
|
||||||
testImplementation("junit:junit:4.13.2")
|
testImplementation("junit:junit:4.13.2")
|
||||||
testImplementation("org.hamcrest:hamcrest-all:1.3")
|
testImplementation("org.hamcrest:hamcrest-all:1.3")
|
||||||
testImplementation("org.mockito:mockito-core:3.12.4")
|
testImplementation("org.mockito:mockito-core:5.23.0")
|
||||||
|
testImplementation("org.mockbukkit.mockbukkit:mockbukkit-v26.1.2:4.113.2")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests use MockBukkit's exact Paper API build because 26.2 registries are not modeled yet.
|
||||||
|
configurations.matching { it.name.startsWith("test") }.configureEach {
|
||||||
|
resolutionStrategy.force("io.papermc.paper:paper-api:26.1.2.build.57-stable")
|
||||||
|
}
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
languageVersion.set(JavaLanguageVersion.of(8))
|
languageVersion.set(JavaLanguageVersion.of(25))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,3 +71,26 @@ tasks {
|
|||||||
// Let the build task produce the final artifact.
|
// Let the build task produce the final artifact.
|
||||||
build { dependsOn(shadowJar) }
|
build { dependsOn(shadowJar) }
|
||||||
}
|
}
|
||||||
|
val checkNoLegacyMaterialApi = tasks.register("checkNoLegacyMaterialApi") {
|
||||||
|
group = "verification"
|
||||||
|
description = "Fails if legacy Bukkit material access returns to production sources."
|
||||||
|
val sources = fileTree("src/main/java") { include("**/*.java") }
|
||||||
|
inputs.files(sources)
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
val violations = sources.files.flatMap { file ->
|
||||||
|
file.readLines().mapIndexedNotNull { index, line ->
|
||||||
|
if ("org.bukkit.material" in line || "state.getData()" in line) {
|
||||||
|
"${file.relativeTo(projectDir)}:${index + 1}"
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
check(violations.isEmpty()) {
|
||||||
|
"Legacy Bukkit material API usage found:\n${violations.joinToString("\n")}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named("check") {
|
||||||
|
dependsOn(checkNoLegacyMaterialApi)
|
||||||
|
}
|
||||||
|
|||||||
+12
-1
@@ -12,6 +12,16 @@ These changes will (most likely) be included in the next version.
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.109.1-tss3] - 2026-08-06
|
||||||
|
### Changed
|
||||||
|
- Updated the build and runtime target to Paper 26.2 and Java 25.
|
||||||
|
- Updated renamed health attributes, potion effects, and entity types for the current Paper API.
|
||||||
|
- Updated Gradle, Shadow, Mockito, and the test harness for Java 25.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Removed legacy Bukkit material access from explosion handling and arena block restoration. Creeper and other block explosions no longer initialize CraftLegacy and DataFixerUpper on the server thread.
|
||||||
|
- Restored support-sensitive blocks without physics after their supporting blocks, avoiding legacy attached-face data while preserving soft restoration.
|
||||||
|
|
||||||
## [0.109] - 2024-10-13
|
## [0.109] - 2024-10-13
|
||||||
### Added
|
### Added
|
||||||
- MobArena now properly supports Vault economy providers registered after MobArena has started. This should make it possible to use custom economy providers that aren't built into Vault, such as those created with Denizen.
|
- MobArena now properly supports Vault economy providers registered after MobArena has started. This should make it possible to use custom economy providers that aren't built into Vault, such as those created with Denizen.
|
||||||
@@ -281,7 +291,8 @@ Thanks to:
|
|||||||
- Swatacular for help with testing bug fixes
|
- Swatacular for help with testing bug fixes
|
||||||
- Haileykins for contributions to the code base
|
- Haileykins for contributions to the code base
|
||||||
|
|
||||||
[Unreleased]: https://github.com/garbagemule/MobArena/compare/0.109...HEAD
|
[Unreleased]: https://git.tss3.us/skywalker3200/MobArena/compare/0.109.1-tss3...master
|
||||||
|
[0.109.1-tss3]: https://git.tss3.us/skywalker3200/MobArena/compare/0.109...0.109.1-tss3
|
||||||
[0.109]: https://github.com/garbagemule/MobArena/compare/0.108...0.109
|
[0.109]: https://github.com/garbagemule/MobArena/compare/0.108...0.109
|
||||||
[0.108]: https://github.com/garbagemule/MobArena/compare/0.107...0.108
|
[0.108]: https://github.com/garbagemule/MobArena/compare/0.107...0.108
|
||||||
[0.107]: https://github.com/garbagemule/MobArena/compare/0.106...0.107
|
[0.107]: https://github.com/garbagemule/MobArena/compare/0.106...0.107
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
@@ -43,10 +43,17 @@ import org.bukkit.attribute.Attribute;
|
|||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockState;
|
import org.bukkit.block.BlockState;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.entity.AbstractArrow;
|
||||||
import org.bukkit.entity.AbstractHorse;
|
import org.bukkit.entity.AbstractHorse;
|
||||||
|
import org.bukkit.entity.Boat;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
|
import org.bukkit.entity.ExperienceOrb;
|
||||||
import org.bukkit.entity.Horse;
|
import org.bukkit.entity.Horse;
|
||||||
|
import org.bukkit.entity.Item;
|
||||||
|
import org.bukkit.entity.Minecart;
|
||||||
|
import org.bukkit.entity.ShulkerBullet;
|
||||||
|
import org.bukkit.entity.TNTPrimed;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.InventoryHolder;
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
import org.bukkit.inventory.InventoryView;
|
import org.bukkit.inventory.InventoryView;
|
||||||
@@ -1026,7 +1033,7 @@ public class ArenaImpl implements Arena
|
|||||||
mount.setTamed(true);
|
mount.setTamed(true);
|
||||||
mount.setOwner(p);
|
mount.setOwner(p);
|
||||||
mount.addPassenger(p);
|
mount.addPassenger(p);
|
||||||
mount.setHealth(mount.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
|
mount.setHealth(mount.getAttribute(Attribute.MAX_HEALTH).getValue());
|
||||||
|
|
||||||
// Add saddle
|
// Add saddle
|
||||||
mount.getInventory().addItem(new ItemStack(Material.SADDLE));
|
mount.getInventory().addItem(new ItemStack(Material.SADDLE));
|
||||||
@@ -1414,15 +1421,14 @@ public class ArenaImpl implements Arena
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (e.getType()) {
|
if (e instanceof Item
|
||||||
case DROPPED_ITEM:
|
|| e instanceof ExperienceOrb
|
||||||
case EXPERIENCE_ORB:
|
|| e instanceof AbstractArrow
|
||||||
case ARROW:
|
|| e instanceof Minecart
|
||||||
case MINECART:
|
|| e instanceof Boat
|
||||||
case BOAT:
|
|| e instanceof TNTPrimed
|
||||||
case PRIMED_TNT:
|
|| e instanceof ShulkerBullet) {
|
||||||
case SHULKER_BULLET:
|
e.remove();
|
||||||
e.remove();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import org.bukkit.Material;
|
|||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.block.BlockState;
|
import org.bukkit.block.BlockState;
|
||||||
|
import org.bukkit.block.PistonMoveReaction;
|
||||||
import org.bukkit.block.Sign;
|
import org.bukkit.block.Sign;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.entity.AbstractHorse;
|
import org.bukkit.entity.AbstractHorse;
|
||||||
@@ -89,10 +90,12 @@ import org.bukkit.event.vehicle.VehicleExitEvent;
|
|||||||
import org.bukkit.inventory.EquipmentSlot;
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
import org.bukkit.inventory.InventoryHolder;
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.material.Attachable;
|
|
||||||
import org.bukkit.material.Bed;
|
import org.bukkit.block.data.Bisected;
|
||||||
import org.bukkit.material.Door;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.material.Redstone;
|
import org.bukkit.block.data.type.Bed;
|
||||||
|
import org.bukkit.block.data.type.Door;
|
||||||
|
|
||||||
import org.bukkit.metadata.MetadataValue;
|
import org.bukkit.metadata.MetadataValue;
|
||||||
import org.bukkit.potion.PotionEffect;
|
import org.bukkit.potion.PotionEffect;
|
||||||
import org.bukkit.potion.PotionEffectType;
|
import org.bukkit.potion.PotionEffectType;
|
||||||
@@ -235,7 +238,7 @@ public class ArenaListener
|
|||||||
r = new RepairableContainer(state);
|
r = new RepairableContainer(state);
|
||||||
else if (state instanceof Sign)
|
else if (state instanceof Sign)
|
||||||
r = new RepairableSign(state);
|
r = new RepairableSign(state);
|
||||||
else if (state.getData() instanceof Attachable)
|
else if (state.getBlockData().getPistonMoveReaction() == PistonMoveReaction.BREAK)
|
||||||
r = new RepairableAttachable(state);
|
r = new RepairableAttachable(state);
|
||||||
else
|
else
|
||||||
r = new RepairableBlock(state);
|
r = new RepairableBlock(state);
|
||||||
@@ -485,12 +488,15 @@ public class ArenaListener
|
|||||||
// Handle all the blocks in the block list.
|
// Handle all the blocks in the block list.
|
||||||
for (Block b : blocks) {
|
for (Block b : blocks) {
|
||||||
BlockState state = b.getState();
|
BlockState state = b.getState();
|
||||||
|
BlockData data = state.getBlockData();
|
||||||
|
|
||||||
if (state.getData() instanceof Door && ((Door) state.getData()).isTopHalf()) {
|
if (data instanceof Door && ((Door) data).getHalf() == Bisected.Half.TOP) {
|
||||||
state = b.getRelative(BlockFace.DOWN).getState();
|
state = b.getRelative(BlockFace.DOWN).getState();
|
||||||
|
data = state.getBlockData();
|
||||||
}
|
}
|
||||||
else if (state.getData() instanceof Bed && ((Bed) state.getData()).isHeadOfBed()) {
|
else if (data instanceof Bed && ((Bed) data).getPart() == Bed.Part.HEAD) {
|
||||||
state = b.getRelative(((Bed) state.getData()).getFacing().getOppositeFace()).getState();
|
state = b.getRelative(((Bed) data).getFacing().getOppositeFace()).getState();
|
||||||
|
data = state.getBlockData();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a Repairable from the block.
|
// Create a Repairable from the block.
|
||||||
@@ -499,11 +505,11 @@ public class ArenaListener
|
|||||||
r = new RepairableContainer(state);
|
r = new RepairableContainer(state);
|
||||||
else if (state instanceof Sign)
|
else if (state instanceof Sign)
|
||||||
r = new RepairableSign(state);
|
r = new RepairableSign(state);
|
||||||
else if (state.getData() instanceof Bed)
|
else if (data instanceof Bed)
|
||||||
r = new RepairableBed(state);
|
r = new RepairableBed(state);
|
||||||
else if (state.getData() instanceof Door)
|
else if (data instanceof Door)
|
||||||
r = new RepairableDoor(state);
|
r = new RepairableDoor(state);
|
||||||
else if (state.getData() instanceof Attachable || state.getData() instanceof Redstone)
|
else if (data.getPistonMoveReaction() == PistonMoveReaction.BREAK)
|
||||||
r = new RepairableAttachable(state);
|
r = new RepairableAttachable(state);
|
||||||
else
|
else
|
||||||
r = new RepairableBlock(state);
|
r = new RepairableBlock(state);
|
||||||
@@ -958,7 +964,7 @@ public class ArenaListener
|
|||||||
// If a potion has harmful effects, remove all players.
|
// If a potion has harmful effects, remove all players.
|
||||||
for (PotionEffect effect : potion.getEffects()) {
|
for (PotionEffect effect : potion.getEffects()) {
|
||||||
PotionEffectType type = effect.getType();
|
PotionEffectType type = effect.getType();
|
||||||
if (type.equals(PotionEffectType.HARM) || type.equals(PotionEffectType.POISON)) {
|
if (type.equals(PotionEffectType.INSTANT_DAMAGE) || type.equals(PotionEffectType.POISON)) {
|
||||||
for (LivingEntity le : event.getAffectedEntities()) {
|
for (LivingEntity le : event.getAffectedEntities()) {
|
||||||
if (le instanceof Player) {
|
if (le instanceof Player) {
|
||||||
event.setIntensity(le, 0.0);
|
event.setIntensity(le, 0.0);
|
||||||
@@ -972,7 +978,7 @@ public class ArenaListener
|
|||||||
// Otherwise, check for monster infighting
|
// Otherwise, check for monster infighting
|
||||||
for (PotionEffect effect : potion.getEffects()) {
|
for (PotionEffect effect : potion.getEffects()) {
|
||||||
PotionEffectType type = effect.getType();
|
PotionEffectType type = effect.getType();
|
||||||
if (type.equals(PotionEffectType.HARM) || type.equals(PotionEffectType.POISON)) {
|
if (type.equals(PotionEffectType.INSTANT_DAMAGE) || type.equals(PotionEffectType.POISON)) {
|
||||||
for (LivingEntity le : event.getAffectedEntities()) {
|
for (LivingEntity le : event.getAffectedEntities()) {
|
||||||
if (!(le instanceof Player)) {
|
if (!(le instanceof Player)) {
|
||||||
event.setIntensity(le, 0.0);
|
event.setIntensity(le, 0.0);
|
||||||
|
|||||||
@@ -226,9 +226,9 @@ public class MASpawnThread implements Runnable
|
|||||||
monsterManager.addMonster(e);
|
monsterManager.addMonster(e);
|
||||||
|
|
||||||
// Set the health.
|
// Set the health.
|
||||||
int health = (int) Math.max(1D, e.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue() * mul);
|
int health = (int) Math.max(1D, e.getAttribute(Attribute.MAX_HEALTH).getValue() * mul);
|
||||||
try {
|
try {
|
||||||
e.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(health);
|
e.getAttribute(Attribute.MAX_HEALTH).setBaseValue(health);
|
||||||
e.setHealth(health);
|
e.setHealth(health);
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
// Spigot... *facepalm*
|
// Spigot... *facepalm*
|
||||||
@@ -266,9 +266,9 @@ public class MASpawnThread implements Runnable
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SWARM:
|
case SWARM:
|
||||||
health = (int) (mul < 1D ? e.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue() * mul : 1);
|
health = (int) (mul < 1D ? e.getAttribute(Attribute.MAX_HEALTH).getValue() * mul : 1);
|
||||||
health = Math.max(1, health);
|
health = Math.max(1, health);
|
||||||
e.setHealth(Math.min(health, e.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue()));
|
e.setHealth(Math.min(health, e.getAttribute(Attribute.MAX_HEALTH).getValue()));
|
||||||
break;
|
break;
|
||||||
case SUPPLY:
|
case SUPPLY:
|
||||||
SupplyWave sw = (SupplyWave) w;
|
SupplyWave sw = (SupplyWave) w;
|
||||||
|
|||||||
@@ -2,37 +2,20 @@ package com.garbagemule.MobArena.repairable;
|
|||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
|
||||||
import org.bukkit.block.BlockState;
|
import org.bukkit.block.BlockState;
|
||||||
import org.bukkit.material.Attachable;
|
|
||||||
|
|
||||||
public class RepairableAttachable extends RepairableBlock
|
public class RepairableAttachable extends RepairableBlock
|
||||||
{
|
{
|
||||||
private int x, y, z;
|
|
||||||
|
|
||||||
public RepairableAttachable(BlockState state)
|
public RepairableAttachable(BlockState state)
|
||||||
{
|
{
|
||||||
super(state);
|
super(state);
|
||||||
|
state.getBlock().setType(Material.STONE, false);
|
||||||
BlockState attached;
|
|
||||||
if (state.getData() instanceof Attachable)
|
|
||||||
attached = state.getBlock().getRelative(((Attachable) state.getData()).getAttachedFace()).getState();
|
|
||||||
else
|
|
||||||
attached = state.getBlock().getRelative(BlockFace.DOWN).getState();
|
|
||||||
|
|
||||||
x = attached.getX();
|
|
||||||
y = attached.getY();
|
|
||||||
z = attached.getZ();
|
|
||||||
|
|
||||||
state.getBlock().setType(Material.STONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void repair()
|
public void repair()
|
||||||
{
|
{
|
||||||
Block b = getWorld().getBlockAt(x,y,z);
|
Block block = getWorld().getBlockAt(getX(), getY(), getZ());
|
||||||
if (b.getType() == Material.AIR)
|
block.setBlockData(getData(), false);
|
||||||
b.setType(Material.STONE);
|
|
||||||
|
|
||||||
super.repair();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.garbagemule.MobArena.repairable;
|
package com.garbagemule.MobArena.repairable;
|
||||||
|
|
||||||
import org.bukkit.block.BlockState;
|
import org.bukkit.block.BlockState;
|
||||||
import org.bukkit.material.Bed;
|
import org.bukkit.block.data.type.Bed;
|
||||||
|
|
||||||
public class RepairableBed extends RepairableBlock
|
public class RepairableBed extends RepairableBlock
|
||||||
{
|
{
|
||||||
@@ -10,12 +10,12 @@ public class RepairableBed extends RepairableBlock
|
|||||||
public RepairableBed(BlockState state)
|
public RepairableBed(BlockState state)
|
||||||
{
|
{
|
||||||
super(state);
|
super(state);
|
||||||
other = state.getBlock().getRelative(((Bed) state.getData()).getFacing()).getState();
|
other = state.getBlock().getRelative(((Bed) state.getBlockData()).getFacing()).getState();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void repair()
|
public void repair()
|
||||||
{
|
{
|
||||||
if (getWorld().getBlockAt(getX(), getY(), getZ()).getState().getData() instanceof Bed)
|
if (getWorld().getBlockAt(getX(), getY(), getZ()).getBlockData() instanceof Bed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
super.repair();
|
super.repair();
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
package com.garbagemule.MobArena.repairable;
|
package com.garbagemule.MobArena.repairable;
|
||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.data.Attachable;
|
import org.bukkit.block.PistonMoveReaction;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.block.data.type.Bed;
|
import org.bukkit.block.data.type.Bed;
|
||||||
import org.bukkit.block.data.type.Door;
|
import org.bukkit.block.data.type.Door;
|
||||||
import org.bukkit.block.data.type.RedstoneWire;
|
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
@@ -30,6 +29,6 @@ public class RepairableComparator implements Comparator<Repairable>
|
|||||||
Material t = r.getType();
|
Material t = r.getType();
|
||||||
BlockData data = r.getData();
|
BlockData data = r.getData();
|
||||||
|
|
||||||
return (data instanceof Attachable || data instanceof RedstoneWire || data instanceof Door || data instanceof Bed || t == Material.LAVA || t == Material.WATER || t == Material.FIRE);
|
return (data.getPistonMoveReaction() == PistonMoveReaction.BREAK || data instanceof Door || data instanceof Bed || t == Material.LAVA || t == Material.WATER || t == Material.FIRE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import org.bukkit.Material;
|
|||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.block.BlockState;
|
import org.bukkit.block.BlockState;
|
||||||
import org.bukkit.material.Door;
|
import org.bukkit.block.data.type.Door;
|
||||||
|
|
||||||
public class RepairableDoor extends RepairableAttachable//RepairableBlock
|
public class RepairableDoor extends RepairableAttachable//RepairableBlock
|
||||||
{
|
{
|
||||||
@@ -24,7 +24,7 @@ public class RepairableDoor extends RepairableAttachable//RepairableBlock
|
|||||||
|
|
||||||
public void repair()
|
public void repair()
|
||||||
{
|
{
|
||||||
if (getWorld().getBlockAt(getX(), getY(), getZ()).getState().getData() instanceof Door)
|
if (getWorld().getBlockAt(getX(), getY(), getZ()).getBlockData() instanceof Door)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Block b = getWorld().getBlockAt(x,y,z);
|
Block b = getWorld().getBlockAt(x,y,z);
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ class SetHealth extends PlayerStep {
|
|||||||
player.setRemainingAir(NORMAL_AIR);
|
player.setRemainingAir(NORMAL_AIR);
|
||||||
player.setFireTicks(NORMAL_FIRE);
|
player.setFireTicks(NORMAL_FIRE);
|
||||||
|
|
||||||
double full = player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
|
double full = player.getAttribute(Attribute.MAX_HEALTH).getValue();
|
||||||
player.setHealth(full);
|
player.setHealth(full);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void undo() {
|
public void undo() {
|
||||||
double max = player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
|
double max = player.getAttribute(Attribute.MAX_HEALTH).getValue();
|
||||||
double capped = Math.min(health, max);
|
double capped = Math.min(health, max);
|
||||||
player.setHealth(capped);
|
player.setHealth(capped);
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class MABoss
|
|||||||
*/
|
*/
|
||||||
public MABoss(LivingEntity entity, double maxHealth) {
|
public MABoss(LivingEntity entity, double maxHealth) {
|
||||||
try {
|
try {
|
||||||
entity.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(maxHealth);
|
entity.getAttribute(Attribute.MAX_HEALTH).setBaseValue(maxHealth);
|
||||||
entity.setHealth(maxHealth);
|
entity.setHealth(maxHealth);
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
// Spigot... *facepalm*
|
// Spigot... *facepalm*
|
||||||
@@ -57,7 +57,7 @@ public class MABoss
|
|||||||
* @return the maximum health of the boss
|
* @return the maximum health of the boss
|
||||||
*/
|
*/
|
||||||
public double getMaxHealth() {
|
public double getMaxHealth() {
|
||||||
return entity.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
|
return entity.getAttribute(Attribute.MAX_HEALTH).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ public class RootTarget implements Ability
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
Player player = (Player) target;
|
Player player = (Player) target;
|
||||||
player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, DURATION, AMPLIFIER));
|
player.addPotionEffect(new PotionEffect(PotionEffectType.SLOWNESS, DURATION, AMPLIFIER));
|
||||||
player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_FALLING, DURATION, AMPLIFIER));
|
player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_FALLING, DURATION, AMPLIFIER));
|
||||||
player.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, DURATION, -AMPLIFIER));
|
player.addPotionEffect(new PotionEffect(PotionEffectType.JUMP_BOOST, DURATION, -AMPLIFIER));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ name: ${project.name}
|
|||||||
author: garbagemule
|
author: garbagemule
|
||||||
main: com.garbagemule.MobArena.MobArena
|
main: com.garbagemule.MobArena.MobArena
|
||||||
version: '${project.version}'
|
version: '${project.version}'
|
||||||
api-version: 1.13
|
api-version: '26.2'
|
||||||
softdepend: [Multiverse-Core,Towny,Heroes,MagicSpells,Vault]
|
softdepend: [Multiverse-Core,Towny,Heroes,MagicSpells,Vault]
|
||||||
commands:
|
commands:
|
||||||
ma:
|
ma:
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public class HandlesSignCreationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void noSignCreationNoAction() {
|
public void noSignCreationNoAction() {
|
||||||
SignChangeEvent event = new SignChangeEvent(null, null, null);
|
SignChangeEvent event = mock(SignChangeEvent.class);
|
||||||
when(creator.create(event)).thenReturn(null);
|
when(creator.create(event)).thenReturn(null);
|
||||||
|
|
||||||
subject.on(event);
|
subject.on(event);
|
||||||
@@ -61,7 +61,8 @@ public class HandlesSignCreationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void passesSignFromCreator() throws Exception {
|
public void passesSignFromCreator() throws Exception {
|
||||||
Player player = mock(Player.class);
|
Player player = mock(Player.class);
|
||||||
SignChangeEvent event = new SignChangeEvent(null, player, null);
|
SignChangeEvent event = mock(SignChangeEvent.class);
|
||||||
|
when(event.getPlayer()).thenReturn(player);
|
||||||
ArenaSign sign = new ArenaSign(location(), null, null, null);
|
ArenaSign sign = new ArenaSign(location(), null, null, null);
|
||||||
when(creator.create(event)).thenReturn(sign);
|
when(creator.create(event)).thenReturn(sign);
|
||||||
|
|
||||||
@@ -75,7 +76,8 @@ public class HandlesSignCreationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void successMessageOnCreation() {
|
public void successMessageOnCreation() {
|
||||||
Player player = mock(Player.class);
|
Player player = mock(Player.class);
|
||||||
SignChangeEvent event = new SignChangeEvent(null, player, null);
|
SignChangeEvent event = mock(SignChangeEvent.class);
|
||||||
|
when(event.getPlayer()).thenReturn(player);
|
||||||
ArenaSign sign = new ArenaSign(location(), null, "castle", "join");
|
ArenaSign sign = new ArenaSign(location(), null, "castle", "join");
|
||||||
when(creator.create(event)).thenReturn(sign);
|
when(creator.create(event)).thenReturn(sign);
|
||||||
|
|
||||||
@@ -87,7 +89,7 @@ public class HandlesSignCreationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void noWriteIfCreatorThrows() {
|
public void noWriteIfCreatorThrows() {
|
||||||
SignChangeEvent event = new SignChangeEvent(null, null, null);
|
SignChangeEvent event = mock(SignChangeEvent.class);
|
||||||
doThrow(IllegalArgumentException.class).when(creator).create(event);
|
doThrow(IllegalArgumentException.class).when(creator).create(event);
|
||||||
|
|
||||||
subject.on(event);
|
subject.on(event);
|
||||||
@@ -98,7 +100,8 @@ public class HandlesSignCreationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void errorMessageIfCreatorThrows() {
|
public void errorMessageIfCreatorThrows() {
|
||||||
Player player = mock(Player.class);
|
Player player = mock(Player.class);
|
||||||
SignChangeEvent event = new SignChangeEvent(null, player, null);
|
SignChangeEvent event = mock(SignChangeEvent.class);
|
||||||
|
when(event.getPlayer()).thenReturn(player);
|
||||||
String message = "it's bad";
|
String message = "it's bad";
|
||||||
doThrow(new IllegalArgumentException(message)).when(creator).create(event);
|
doThrow(new IllegalArgumentException(message)).when(creator).create(event);
|
||||||
|
|
||||||
@@ -109,7 +112,7 @@ public class HandlesSignCreationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void noStorageIfWriterThrows() throws Exception {
|
public void noStorageIfWriterThrows() throws Exception {
|
||||||
SignChangeEvent event = new SignChangeEvent(null, null, null);
|
SignChangeEvent event = mock(SignChangeEvent.class);
|
||||||
ArenaSign sign = new ArenaSign(null, null, null, null);
|
ArenaSign sign = new ArenaSign(null, null, null, null);
|
||||||
when(creator.create(event)).thenReturn(sign);
|
when(creator.create(event)).thenReturn(sign);
|
||||||
doThrow(IOException.class).when(writer).write(sign);
|
doThrow(IOException.class).when(writer).write(sign);
|
||||||
@@ -122,7 +125,8 @@ public class HandlesSignCreationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void errorMessageIfWriterThrows() throws Exception {
|
public void errorMessageIfWriterThrows() throws Exception {
|
||||||
Player player = mock(Player.class);
|
Player player = mock(Player.class);
|
||||||
SignChangeEvent event = new SignChangeEvent(null, player, null);
|
SignChangeEvent event = mock(SignChangeEvent.class);
|
||||||
|
when(event.getPlayer()).thenReturn(player);
|
||||||
ArenaSign sign = new ArenaSign(null, null, null, null);
|
ArenaSign sign = new ArenaSign(null, null, null, null);
|
||||||
when(creator.create(event)).thenReturn(sign);
|
when(creator.create(event)).thenReturn(sign);
|
||||||
IOException exception = new IOException("it's bad");
|
IOException exception = new IOException("it's bad");
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class SignCreatorTest {
|
|||||||
@Test
|
@Test
|
||||||
public void noHeaderNoAction() {
|
public void noHeaderNoAction() {
|
||||||
String[] lines = {"ma", "castle", "join", "cool-sign"};
|
String[] lines = {"ma", "castle", "join", "cool-sign"};
|
||||||
SignChangeEvent event = new SignChangeEvent(null, null, lines);
|
SignChangeEvent event = event(lines, null);
|
||||||
|
|
||||||
ArenaSign result = subject.create(event);
|
ArenaSign result = subject.create(event);
|
||||||
|
|
||||||
@@ -202,10 +202,12 @@ public class SignCreatorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private SignChangeEvent event(String[] lines, Location location) {
|
private SignChangeEvent event(String[] lines, Location location) {
|
||||||
|
SignChangeEvent event = mock(SignChangeEvent.class);
|
||||||
|
when(event.getLine(anyInt())).thenAnswer(invocation -> lines[invocation.getArgument(0)]);
|
||||||
Block block = mock(Block.class);
|
Block block = mock(Block.class);
|
||||||
when(block.getLocation()).thenReturn(location);
|
when(block.getLocation()).thenReturn(location);
|
||||||
Player player = mock(Player.class);
|
when(event.getBlock()).thenReturn(block);
|
||||||
return new SignChangeEvent(block, player, lines);
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ package com.garbagemule.MobArena.things;
|
|||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
|
import org.mockbukkit.mockbukkit.MockBukkit;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.*;
|
import static org.hamcrest.CoreMatchers.*;
|
||||||
import static org.hamcrest.MatcherAssert.*;
|
import static org.hamcrest.MatcherAssert.*;
|
||||||
@@ -13,6 +16,15 @@ import static org.mockito.Mockito.*;
|
|||||||
public class ItemStackThingParserTest {
|
public class ItemStackThingParserTest {
|
||||||
|
|
||||||
private ItemStackThingParser subject;
|
private ItemStackThingParser subject;
|
||||||
|
@BeforeClass
|
||||||
|
public static void startServer() {
|
||||||
|
MockBukkit.mock();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void stopServer() {
|
||||||
|
MockBukkit.unmock();
|
||||||
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
@@ -107,7 +119,7 @@ public class ItemStackThingParserTest {
|
|||||||
subject.parse(input);
|
subject.parse(input);
|
||||||
|
|
||||||
verify(first).parse(input);
|
verify(first).parse(input);
|
||||||
verifyZeroInteractions(third);
|
verifyNoInteractions(third);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public class ThingManagerTest {
|
|||||||
|
|
||||||
verify(first).parse("thing");
|
verify(first).parse("thing");
|
||||||
verify(second).parse("thing");
|
verify(second).parse("thing");
|
||||||
verifyZeroInteractions(third);
|
verifyNoInteractions(third);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user