Skip to content

Commit 267d785

Browse files
authored
Merge pull request #159 from BentoBoxWorld/develop
Release 4.7.0
2 parents 8c72490 + 1f902b7 commit 267d785

File tree

12 files changed

+268
-50
lines changed

12 files changed

+268
-50
lines changed

pom.xml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@
4646
<junit.version>5.10.2</junit.version>
4747
<mockito.version>5.11.0</mockito.version>
4848
<!-- More visible way how to change dependency versions -->
49-
<paper.version>1.21.10-R0.1-SNAPSHOT</paper.version>
49+
<paper.version>1.21.11-R0.1-SNAPSHOT</paper.version>
5050
<bentobox.version>3.10.0</bentobox.version>
5151
<!-- Revision variable removes warning about dynamic version -->
5252
<revision>${build.version}-SNAPSHOT</revision>
5353
<!-- This allows to change between versions and snapshots. -->
54-
<build.version>4.6.0</build.version>
54+
<build.version>4.7.0</build.version>
5555
<build.number>-LOCAL</build.number>
5656
<!-- Sonar Cloud -->
5757
<sonar.projectKey>BentoBoxWorld_Border</sonar.projectKey>
@@ -210,6 +210,11 @@
210210
<version>3.14.1</version>
211211
<configuration>
212212
<release>${java.version}</release>
213+
<fork>true</fork>
214+
<compilerArgs>
215+
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg>
216+
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
217+
</compilerArgs>
213218
</configuration>
214219
</plugin>
215220
<plugin>

src/main/java/world/bentobox/border/Border.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import world.bentobox.border.listeners.BorderShower;
2020
import world.bentobox.border.listeners.PlayerListener;
2121
import world.bentobox.border.listeners.ShowBarrier;
22-
import world.bentobox.border.listeners.ShowVirtualWorldBorder;
22+
import world.bentobox.border.listeners.ShowWorldBorder;
2323

2424
public class Border extends Addon {
2525

@@ -71,7 +71,7 @@ public void onDisable() {
7171

7272
private BorderShower createBorder() {
7373
BorderShower customBorder = new ShowBarrier(this);
74-
BorderShower wbapiBorder = new ShowVirtualWorldBorder(this);
74+
BorderShower wbapiBorder = new ShowWorldBorder(this);
7575
return new PerPlayerBorderProxy(this, customBorder, wbapiBorder);
7676
}
7777

@@ -131,4 +131,5 @@ private void registerPlaceholders()
131131
orElse(getSettings().getType()).
132132
getCommandLabel());
133133
}
134+
134135
}

src/main/java/world/bentobox/border/PerPlayerBorderProxy.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package world.bentobox.border;
22

3+
import java.util.Optional;
4+
5+
import org.bukkit.entity.Entity;
36
import org.bukkit.entity.Player;
7+
48
import world.bentobox.bentobox.api.metadata.MetaDataValue;
59
import world.bentobox.bentobox.api.user.User;
610
import world.bentobox.bentobox.database.objects.Island;
711
import world.bentobox.border.listeners.BorderShower;
812

9-
import java.util.Optional;
10-
1113
public final class PerPlayerBorderProxy implements BorderShower {
1214

1315
public static final String BORDER_BORDERTYPE_META_DATA = "Border_bordertype";
@@ -76,11 +78,11 @@ private BorderType getDefaultBorderType() {
7678
}
7779

7880
@Override
79-
public void teleportPlayer(Player player) {
81+
public void teleportEntity(Border addon, Entity player) {
8082
if (getBorderType(User.getInstance(player)) == BorderType.BARRIER) {
81-
customBorder.teleportPlayer(player);
83+
customBorder.teleportEntity(addon, player);
8284
} else {
83-
vanillaBorder.teleportPlayer(player);
85+
vanillaBorder.teleportEntity(addon, player);
8486
}
8587

8688
}

src/main/java/world/bentobox/border/Settings.java

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,28 @@ public class Settings implements ConfigObject {
2222
private Set<String> disabledGameModes = new HashSet<>();
2323

2424
@ConfigComment("")
25-
@ConfigComment("Border type. Options are VANILLA, which uses the vanillia-style board or BARRIER,")
25+
@ConfigComment("Border type. Options are VANILLA, which uses the vanilla-style boarder or BARRIER,")
2626
@ConfigComment("which uses particles and barrier blocks. If players have permission to use the barrier type")
2727
@ConfigComment("they may override this option. If they do not have permission or lose the permission")
2828
@ConfigComment("then this setting will be used.")
2929
@ConfigEntry(path = "type")
3030
private BorderType type = BorderType.VANILLA;
3131

32+
public enum BorderColor {
33+
RED, GREEN, BLUE
34+
}
35+
@ConfigComment("")
36+
@ConfigComment("Vanilla border color. Only applies if the border type is VANILLA.")
37+
@ConfigComment("Selection is RED, GREEN, BLUE.")
38+
@ConfigEntry(path = "color")
39+
private BorderColor color = BorderColor.BLUE;
40+
41+
@ConfigComment("")
42+
@ConfigComment("Bounce items back inside the border if they are thrown by a player.")
43+
@ConfigComment("Without this, items can be thrown outside the border.")
44+
@ConfigEntry(path = "bounce-back")
45+
private boolean bounceBack = true;
46+
3247
@ConfigComment("")
3348
@ConfigComment("Teleport players back inside the border if they somehow get outside.")
3449
@ConfigComment("This will teleport players back inside if they toggle the border with a command.")
@@ -192,4 +207,32 @@ public boolean isReturnTeleportBlock() {
192207
public void setReturnTeleportBlock(boolean returnTeleportBlock) {
193208
this.returnTeleportBlock = returnTeleportBlock;
194209
}
210+
211+
/**
212+
* @return the bounceBack
213+
*/
214+
public boolean isBounceBack() {
215+
return bounceBack;
216+
}
217+
218+
/**
219+
* @param bounceBack the bounceBack to set
220+
*/
221+
public void setBounceBack(boolean bounceBack) {
222+
this.bounceBack = bounceBack;
223+
}
224+
225+
/**
226+
* @return the color
227+
*/
228+
public BorderColor getColor() {
229+
return color;
230+
}
231+
232+
/* *
233+
* @param color the color to set
234+
*/
235+
public void setColor(BorderColor color) {
236+
this.color = color;
237+
}
195238
}

src/main/java/world/bentobox/border/listeners/BorderShower.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
package world.bentobox.border.listeners;
22

3+
import org.bukkit.Location;
4+
import org.bukkit.entity.Entity;
35
import org.bukkit.entity.Player;
6+
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
7+
import org.bukkit.util.Vector;
48

59
import world.bentobox.bentobox.api.user.User;
610
import world.bentobox.bentobox.database.objects.Island;
11+
import world.bentobox.bentobox.util.Util;
12+
import world.bentobox.border.Border;
713

814
/**
915
* A border shower class
@@ -44,9 +50,19 @@ public default void refreshView(User user, Island island){
4450
}
4551

4652
/**
47-
* Teleports player back within the island space they are in
48-
* @param player player
53+
* Teleports an entity, typically a player back within the island space they are in
54+
* @param entity entity
4955
*/
50-
public void teleportPlayer(Player player);
56+
public default void teleportEntity(Border addon, Entity entity) {
57+
addon.getIslands().getIslandAt(entity.getLocation()).ifPresent(i -> {
58+
Vector unitVector = i.getCenter().toVector().subtract(entity.getLocation().toVector()).normalize()
59+
.multiply(new Vector(1, 0, 1));
60+
// Get distance from border
61+
Location to = entity.getLocation().toVector().add(unitVector).toLocation(entity.getWorld());
62+
to.setPitch(entity.getLocation().getPitch());
63+
to.setYaw(entity.getLocation().getYaw());
64+
Util.teleportAsync(entity, to, TeleportCause.PLUGIN);
65+
});
66+
}
5167

5268
}

src/main/java/world/bentobox/border/listeners/PlayerListener.java

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.bukkit.Material;
1515
import org.bukkit.block.BlockFace;
1616
import org.bukkit.entity.Entity;
17+
import org.bukkit.entity.Item;
1718
import org.bukkit.entity.Player;
1819
import org.bukkit.event.EventHandler;
1920
import org.bukkit.event.EventPriority;
@@ -22,23 +23,26 @@
2223
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
2324
import org.bukkit.event.entity.EntityDismountEvent;
2425
import org.bukkit.event.entity.EntityMountEvent;
26+
import org.bukkit.event.entity.PlayerDeathEvent;
27+
import org.bukkit.event.player.PlayerDropItemEvent;
2528
import org.bukkit.event.player.PlayerJoinEvent;
2629
import org.bukkit.event.player.PlayerMoveEvent;
2730
import org.bukkit.event.player.PlayerQuitEvent;
2831
import org.bukkit.event.player.PlayerRespawnEvent;
2932
import org.bukkit.event.player.PlayerTeleportEvent;
3033
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
3134
import org.bukkit.event.vehicle.VehicleMoveEvent;
35+
import org.bukkit.scheduler.BukkitRunnable;
3236
import org.bukkit.scheduler.BukkitTask;
3337
import org.bukkit.util.NumberConversions;
3438
import org.bukkit.util.RayTraceResult;
3539
import org.bukkit.util.Vector;
3640

37-
import world.bentobox.bentobox.BentoBox;
3841
import world.bentobox.bentobox.api.events.island.IslandProtectionRangeChangeEvent;
3942
import world.bentobox.bentobox.api.flags.Flag;
4043
import world.bentobox.bentobox.api.metadata.MetaDataValue;
4144
import world.bentobox.bentobox.api.user.User;
45+
import world.bentobox.bentobox.database.objects.Island;
4246
import world.bentobox.bentobox.util.Util;
4347
import world.bentobox.border.Border;
4448
import world.bentobox.border.BorderType;
@@ -111,7 +115,7 @@ public void onPlayerDamage(EntityDamageEvent e) {
111115
}
112116
Material type = p.getLocation().getBlock().getRelative(BlockFace.DOWN).getType();
113117
if (type == Material.AIR) {
114-
((BorderShower) show).teleportPlayer(p);
118+
((BorderShower) show).teleportEntity(addon, p);
115119
e.setCancelled(true);
116120
}
117121
}
@@ -204,8 +208,13 @@ public void onPlayerLeaveIsland(PlayerMoveEvent e) {
204208
Util.teleportAsync(p, from).thenRun(() -> inTeleport.remove(p.getUniqueId()));
205209
return;
206210
}
207-
// Backtrack
208-
addon.getIslands().getIslandAt(p.getLocation()).ifPresent(i -> {
211+
// Backtrack - try to find island at current location, or fall back to the player's own island
212+
Optional<Island> optionalIsland = addon.getIslands().getIslandAt(p.getLocation());
213+
if (optionalIsland.isEmpty()) {
214+
optionalIsland = Optional
215+
.ofNullable(addon.getIslands().getIsland(p.getWorld(), User.getInstance(p)));
216+
}
217+
optionalIsland.ifPresent(i -> {
209218
Vector unitVector = i.getProtectionCenter().toVector().subtract(p.getLocation().toVector()).normalize()
210219
.multiply(new Vector(1,0,1));
211220
if (unitVector.lengthSquared() <= 0D) {
@@ -259,7 +268,10 @@ private boolean outsideCheck(Player player, Location from, Location to) {
259268
|| !user.getMetaData(BorderShower.BORDER_STATE_META_DATA).map(MetaDataValue::asBoolean).orElse(addon.getSettings().isShowByDefault())) {
260269
return false;
261270
}
262-
return addon.getIslands().getIslandAt(to).filter(i -> !i.onIsland(to)).isPresent();
271+
Optional<Island> islandAt = addon.getIslands().getIslandAt(to);
272+
// Player is outside if they are on an island but not within its protection zone,
273+
// or if they are not on any island at all (e.g., pushed out by piston)
274+
return islandAt.isEmpty() || islandAt.filter(i -> !i.onIsland(to)).isPresent();
263275
}
264276

265277
/**
@@ -338,8 +350,8 @@ public void onVehicleMove(VehicleMoveEvent e) {
338350
// Remove head movement
339351
if (!e.getFrom().toVector().equals(e.getTo().toVector())) {
340352
e.getVehicle().getPassengers().stream().filter(Player.class::isInstance).map(Player.class::cast)
341-
.filter(this::isOn).forEach(p -> addon.getIslands().getIslandAt(p.getLocation())
342-
.ifPresent(i -> show.refreshView(User.getInstance(p), i)));
353+
.filter(this::isOn).forEach(p -> addon.getIslands().getIslandAt(p.getLocation())
354+
.ifPresent(i -> show.refreshView(User.getInstance(p), i)));
343355
}
344356
}
345357

@@ -357,4 +369,61 @@ public void onProtectionRangeChange(IslandProtectionRangeChangeEvent e) {
357369
}
358370
});
359371
}
372+
373+
/**
374+
* Bounces items back to inside the barrier if thrown by a player
375+
* @param event event
376+
*/
377+
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
378+
public void onItemDrop(PlayerDropItemEvent event) {
379+
if (addon.getSettings().isBounceBack()
380+
&& addon.inGameWorld(event.getPlayer().getWorld())
381+
&& isOn(event.getPlayer())
382+
) {
383+
// Get this island
384+
addon.getIslands().getIslandAt(event.getPlayer().getLocation()).ifPresent(is -> trackItem(event.getItemDrop(), is));
385+
}
386+
}
387+
388+
/**
389+
* Bounces items back to inside the barrier if dropped when a player dies
390+
* @param event event
391+
*/
392+
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
393+
public void onPlayerDeath(PlayerDeathEvent event) {
394+
if (addon.getSettings().isBounceBack()
395+
&& addon.inGameWorld(event.getPlayer().getWorld())
396+
&& isOn(event.getPlayer())) {
397+
// Get this island
398+
addon.getIslands().getIslandAt(event.getPlayer().getLocation()).ifPresent(is -> {
399+
event.getDrops().forEach(item -> trackItem(event.getPlayer().getWorld().dropItemNaturally(event.getPlayer().getLocation(), item), is));
400+
event.getDrops().clear(); // We handled them
401+
});
402+
}
403+
}
404+
405+
private void trackItem(Item item, Island island) {
406+
new BukkitRunnable() {
407+
int ticksActive = 0;
408+
409+
@Override
410+
public void run() {
411+
// Stop tracking if the item is picked up, despawned, or 20 seconds have passed
412+
if (!item.isValid() || ticksActive > 400) {
413+
this.cancel();
414+
return;
415+
}
416+
417+
Location loc = item.getLocation();
418+
// Check if the item is going outside the border
419+
if (!island.onIsland(loc)) {
420+
// Reverse the direction
421+
item.setVelocity(item.getVelocity().multiply(-0.5));
422+
this.cancel();
423+
}
424+
ticksActive++;
425+
}
426+
}.runTaskTimer(addon.getPlugin(), 1L, 2L); // Check every 2 ticks (0.1 seconds)
427+
}
428+
360429
}

src/main/java/world/bentobox/border/listeners/ShowBarrier.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
import org.bukkit.Material;
1313
import org.bukkit.Particle;
1414
import org.bukkit.block.data.BlockData;
15+
import org.bukkit.entity.Entity;
1516
import org.bukkit.entity.Player;
1617
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
1718
import org.bukkit.util.Vector;
1819

1920
import com.google.common.base.Enums;
2021

21-
import world.bentobox.bentobox.BentoBox;
2222
import world.bentobox.bentobox.api.metadata.MetaDataValue;
2323
import world.bentobox.bentobox.api.user.User;
2424
import world.bentobox.bentobox.database.objects.Island;
@@ -136,7 +136,7 @@ private void showPlayer(Player player, int i, int j, int k, boolean max) {
136136
if (addon.getSettings().isUseBarrierBlocks()
137137
&& player.getLocation().getBlockX() == i
138138
&& player.getLocation().getBlockZ() == k) {
139-
teleportPlayer(player);
139+
teleportEntity(player);
140140
}
141141

142142
Location l = new Location(player.getWorld(), i, j, k);
@@ -157,17 +157,17 @@ private void showPlayer(Player player, int i, int j, int k, boolean max) {
157157

158158
/**
159159
* Teleport player back within the island space they are in
160-
* @param p player
160+
* @param entity player or entity
161161
*/
162-
public void teleportPlayer(Player p) {
163-
addon.getIslands().getIslandAt(p.getLocation()).ifPresent(i -> {
164-
Vector unitVector = i.getCenter().toVector().subtract(p.getLocation().toVector()).normalize()
162+
public void teleportEntity(Entity entity) {
163+
addon.getIslands().getIslandAt(entity.getLocation()).ifPresent(i -> {
164+
Vector unitVector = i.getCenter().toVector().subtract(entity.getLocation().toVector()).normalize()
165165
.multiply(new Vector(1, 0, 1));
166166
// Get distance from border
167-
Location to = p.getLocation().toVector().add(unitVector).toLocation(p.getWorld());
168-
to.setPitch(p.getLocation().getPitch());
169-
to.setYaw(p.getLocation().getYaw());
170-
Util.teleportAsync(p, to, TeleportCause.PLUGIN);
167+
Location to = entity.getLocation().toVector().add(unitVector).toLocation(entity.getWorld());
168+
to.setPitch(entity.getLocation().getPitch());
169+
to.setYaw(entity.getLocation().getYaw());
170+
Util.teleportAsync(entity, to, TeleportCause.PLUGIN);
171171
});
172172
}
173173

0 commit comments

Comments
 (0)