Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
<!-- Do not change unless you want different name for local builds. -->
<build.number>-LOCAL</build.number>
<!-- This allows to change between versions. -->
<build.version>3.4.0</build.version>
<build.version>3.4.1</build.version>

<sonar.projectKey>BentoBoxWorld_Boxed</sonar.projectKey>
<sonar.organization>bentobox-world</sonar.organization>
Expand Down
49 changes: 49 additions & 0 deletions release-notes-3.4.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
Boxed 3.4.0 brings support for **Trial Chambers** and their trial spawners, fixes cross-game-mode advancement resets, and modernises the entire build and test stack for Paper 1.21.11 / BentoBox 3.13.0.

## Highlights

* **Trial Chambers support** — Boxed now captures and restores Trial Spawner state (including the normal *and* ominous configurations) when structures are pulled from the seed world into a player's box, and recognises `trial_chambers` as a tracked structure.
* **No more cross-game-mode progress loss** — Boxed no longer clears a player's advancements and statistics when an island is reset in a *different*, non-Boxed game mode.
* **Modernised build & test stack** — upgraded to Paper 1.21.11 and BentoBox 3.13.0, with the test suite migrated to JUnit 5 + Mockito + MockBukkit.

## New Features

### Trial Chambers & Trial Spawners

Trial Chambers can now appear inside player boxes. When a box is generated from the seed world, Boxed copies the Trial Spawner tile-entity data so the spawners function correctly, preserving whether each spawner is in its **normal** or **ominous** configuration. Trial Chambers are also tracked for advancement-driven box growth. [[PR #123](https://github.com/BentoBoxWorld/Boxed/pull/123)]

## Bug Fixes

* **Advancement/statistic reset leaked across game modes** — `IslandNewIslandEvent` handling now no-ops unless the reset island belongs to a Boxed world, so resetting an island in another game mode no longer wipes Boxed progress. [[PR #125](https://github.com/BentoBoxWorld/Boxed/pull/125)]
* **Structure pasting into deleted islands** — pending structure pastes are now cancelled when an island is deleted, preventing structures being placed into a box that no longer exists.
* **Ominous trial spawners restored incorrectly** — trial spawners now restore the correct configuration rather than always applying the normal one.

## Other Improvements

* **Test suite migration** — replaced the PowerMock-based setup with JUnit 5 (Jupiter), Mockito `mockStatic`, and MockBukkit, and expanded coverage with new listener and placeholder tests (113 tests).
* **Reliable test dependency** — MockBukkit is now pinned to the stable Maven Central artifact `org.mockbukkit.mockbukkit:mockbukkit-v1.21:4.110.0` instead of a floating jitpack snapshot that could break the build without any code change.
* **Documentation** — the README now documents Flags, Placeholders, `structures.yml`, config options, and Regionerator usage. [[PR #124](https://github.com/BentoBoxWorld/Boxed/pull/124)]

## Compatibility

✔️ BentoBox API 3.13.0
✔️ Minecraft 1.21.x – 26.1.x (Paper 1.21.11)
✔️ Java 21

## Upgrading

1. Stop your server.
2. Replace the old `Boxed` jar in `plugins/BentoBox/addons` with this release.
3. Ensure BentoBox is **3.13.0 or newer**.
4. Start the server.

> **Note:** Trial Chambers are captured from the seed world when a box is generated, so boxes created *before* 3.4.0 will not retroactively gain Trial Chambers. New boxes (and newly expanded regions) will include them.

## What's Changed

* Add trial chambers support: fix trial spawner tile entity copying and advancement tracking by @Copilot in https://github.com/BentoBoxWorld/Boxed/pull/123
* Update Boxed README: add Flags, Placeholders, structures.yml, config options, and Regionerator docs by @Copilot in https://github.com/BentoBoxWorld/Boxed/pull/124
* Prevent Boxed from resetting player progress on non-Boxed island resets by @Copilot in https://github.com/BentoBoxWorld/Boxed/pull/125
* Release 3.4.0 (Paper 1.21.11 / BentoBox 3.13.0, JUnit 5 + MockBukkit test migration, build fixes) by @tastybento in https://github.com/BentoBoxWorld/Boxed/pull/126

**Full Changelog**: https://github.com/BentoBoxWorld/Boxed/compare/3.3.0...3.4.0
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public boolean canExecute(User user, String label, List<String> args) {
// Initialize
sr = StructureRotation.NONE;
mirror = Mirror.NONE;
noMobs = false;

// Check world
if (!((Boxed) getAddon()).inWorld(getWorld())) {
Expand All @@ -100,7 +101,7 @@ public boolean canExecute(User user, String label, List<String> args) {
* 6. place <structure> ~ ~ ~ ROTATION MIRROR
* 7. place <structure> ~ ~ ~ ROTATION MIRROR NO_MOBS
*/
if (args.isEmpty() || args.size() == 2 || args.size() == 3 || args.size() > 6) {
if (args.isEmpty() || args.size() == 2 || args.size() == 3 || args.size() > 7) {
this.showHelp(this, user);
return false;
}
Expand Down Expand Up @@ -246,8 +247,7 @@ private boolean undoLastPlacement(User user) {
if (lastRecord.removedBlocks().containsKey(v)) {
return lastRecord.removedBlocks().get(v).createBlockState();
}
BlockState airState = Material.AIR.createBlockData().createBlockState();
return airState;
return Material.AIR.createBlockData().createBlockState();
};

s.place(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.bukkit.block.BlockState;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.block.TrialSpawner;
import org.bukkit.spawner.TrialSpawnerConfiguration;
import org.bukkit.entity.Entity;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.LimitedRegion;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ protected List<EntityData> getEnts(Chunk chunk) {
return this.setEntities(Arrays.stream(chunk.getEntities())
.filter(Objects::nonNull)
.filter(e -> !(e instanceof Player))
.filter(e -> e instanceof LivingEntity)
.filter(LivingEntity.class::isInstance)
.map(LivingEntity.class::cast)
.toList());
}
Expand All @@ -98,14 +98,14 @@ private List<EntityData> setEntities(Collection<LivingEntity> entities) {
bpe.setColor(c.getColor());
}
}
if (entity instanceof Tameable) {
bpe.setTamed(((Tameable)entity).isTamed());
if (entity instanceof Tameable tameable) {
bpe.setTamed(tameable.isTamed());
}
if (entity instanceof ChestedHorse) {
bpe.setChest(((ChestedHorse)entity).isCarryingChest());
if (entity instanceof ChestedHorse chestedHorse) {
bpe.setChest(chestedHorse.isCarryingChest());
}
// Only set if child. Most animals are adults
if (entity instanceof Ageable && !((Ageable)entity).isAdult()) {
if (entity instanceof Ageable ageable && !ageable.isAdult()) {
bpe.setAdult(false);
}
if (entity instanceof AbstractHorse horse) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
import world.bentobox.bentobox.api.events.island.IslandResettedEvent;
import world.bentobox.bentobox.database.Database;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.nms.AbstractMetaData;
import world.bentobox.bentobox.util.Pair;
import world.bentobox.bentobox.util.Util;
import world.bentobox.boxed.Boxed;
Expand Down Expand Up @@ -236,7 +235,7 @@ public void onChunkLoad(ChunkLoadEvent e) {
if (!(addon.inWorld(chunk.getWorld()))) {
return;
}
Pair<Integer, Integer> chunkCoords = new Pair<Integer, Integer>(chunk.getX(), chunk.getZ());
Pair<Integer, Integer> chunkCoords = new Pair<>(chunk.getX(), chunk.getZ());
if (pending.containsKey(chunkCoords)) {
Iterator<StructureRecord> it = pending.get(chunkCoords).iterator();
while (it.hasNext()) {
Expand Down Expand Up @@ -368,7 +367,7 @@ public void onIslandDeleted(IslandDeleteEvent event) {
for (List<StructureRecord> records : pending.values()) {
records.removeIf(record -> event.getIsland().inIslandSpace(record.location()));
}
pending.values().removeIf(list -> list.isEmpty());
pending.values().removeIf(List::isEmpty);

// Remove from pending structures in database
Map<Pair<Integer, Integer>, List<StructureRecord>> readyToBuild = loadToDos().getReadyToBuild();
Expand Down Expand Up @@ -578,7 +577,7 @@ private static void processJigsaw(Block b, StructureRotation structureRotation,
return;
}
BoxedJigsawBlock bjb = gson.fromJson(data, BoxedJigsawBlock.class);
String finalState = correctDirection(bjb.getFinal_state(), structureRotation);
String finalState = correctDirection(bjb.getFinalState(), structureRotation);
BlockData bd = Bukkit.createBlockData(finalState);
b.setBlockData(bd);
if (!bjb.getPool().equalsIgnoreCase("minecraft:empty") && pasteMobs) {
Expand Down
12 changes: 7 additions & 5 deletions src/main/java/world/bentobox/boxed/objects/BoxedJigsawBlock.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package world.bentobox.boxed.objects;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

/**
* This replicates a jigsaw block.
Expand All @@ -10,7 +11,8 @@
public class BoxedJigsawBlock {
// final_state:"minecraft:polished_blackstone_bricks",joint:"aligned",name:"minecraft:empty",pool:"minecraft:bastion/bridge/legs",target:"minecraft:leg_connector"
@Expose
private String final_state;
@SerializedName("final_state")
private String finalState;
@Expose
private String joint;
@Expose
Expand All @@ -20,10 +22,10 @@ public class BoxedJigsawBlock {
@Expose
private String target;
/**
* @return the final_state
* @return the finalState
*/
public String getFinal_state() {
return final_state;
public String getFinalState() {
return finalState;
}
/**
* @return the joint
Expand Down Expand Up @@ -51,7 +53,7 @@ public String getTarget() {
}
@Override
public String toString() {
return "BoxedJigsawBlock [" + (final_state != null ? "final_state=" + final_state + ", " : "")
return "BoxedJigsawBlock [" + (finalState != null ? "finalState=" + finalState + ", " : "")
+ (joint != null ? "joint=" + joint + ", " : "") + (name != null ? "name=" + name + ", " : "")
+ (pool != null ? "pool=" + pool + ", " : "") + (target != null ? "target=" + target : "") + "]";
}
Expand Down
Loading
Loading