Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
9 changes: 7 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@
<junit.version>5.10.2</junit.version>
<mockito.version>5.11.0</mockito.version>
<!-- More visible way how to change dependency versions -->
<paper.version>1.21.10-R0.1-SNAPSHOT</paper.version>
<paper.version>1.21.11-R0.1-SNAPSHOT</paper.version>
<bentobox.version>3.10.0</bentobox.version>
<!-- Revision variable removes warning about dynamic version -->
<revision>${build.version}-SNAPSHOT</revision>
<!-- This allows to change between versions and snapshots. -->
<build.version>4.6.0</build.version>
<build.version>4.7.0</build.version>
<build.number>-LOCAL</build.number>
<!-- Sonar Cloud -->
<sonar.projectKey>BentoBoxWorld_Border</sonar.projectKey>
Expand Down Expand Up @@ -210,6 +210,11 @@
<version>3.14.1</version>
<configuration>
<release>${java.version}</release>
<fork>true</fork>
<compilerArgs>
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg>
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/world/bentobox/border/Border.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import world.bentobox.border.listeners.BorderShower;
import world.bentobox.border.listeners.PlayerListener;
import world.bentobox.border.listeners.ShowBarrier;
import world.bentobox.border.listeners.ShowVirtualWorldBorder;
import world.bentobox.border.listeners.ShowWorldBorder;

public class Border extends Addon {

Expand Down Expand Up @@ -71,7 +71,7 @@ public void onDisable() {

private BorderShower createBorder() {
BorderShower customBorder = new ShowBarrier(this);
BorderShower wbapiBorder = new ShowVirtualWorldBorder(this);
BorderShower wbapiBorder = new ShowWorldBorder(this);
return new PerPlayerBorderProxy(this, customBorder, wbapiBorder);
}

Expand Down Expand Up @@ -131,4 +131,5 @@ private void registerPlaceholders()
orElse(getSettings().getType()).
getCommandLabel());
}

}
12 changes: 7 additions & 5 deletions src/main/java/world/bentobox/border/PerPlayerBorderProxy.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package world.bentobox.border;

import java.util.Optional;

import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;

import world.bentobox.bentobox.api.metadata.MetaDataValue;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.border.listeners.BorderShower;

import java.util.Optional;

public final class PerPlayerBorderProxy implements BorderShower {

public static final String BORDER_BORDERTYPE_META_DATA = "Border_bordertype";
Expand Down Expand Up @@ -76,11 +78,11 @@ private BorderType getDefaultBorderType() {
}

@Override
public void teleportPlayer(Player player) {
public void teleportEntity(Border addon, Entity player) {
if (getBorderType(User.getInstance(player)) == BorderType.BARRIER) {
customBorder.teleportPlayer(player);
customBorder.teleportEntity(addon, player);
} else {
vanillaBorder.teleportPlayer(player);
vanillaBorder.teleportEntity(addon, player);
}

}
Expand Down
45 changes: 44 additions & 1 deletion src/main/java/world/bentobox/border/Settings.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,28 @@ public class Settings implements ConfigObject {
private Set<String> disabledGameModes = new HashSet<>();

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

public enum BorderColor {
RED, GREEN, BLUE
}
@ConfigComment("")
@ConfigComment("Vanilla border color. Only applies if the border type is VANILLA.")
@ConfigComment("Selection is RED, GREEN, BLUE.")
@ConfigEntry(path = "color")
private BorderColor color = BorderColor.BLUE;

@ConfigComment("")
@ConfigComment("Bounce items back inside the border if they are thrown by a player.")
@ConfigComment("Without this, items can be thrown outside the border.")
@ConfigEntry(path = "bounce-back")
private boolean bounceBack = true;

@ConfigComment("")
@ConfigComment("Teleport players back inside the border if they somehow get outside.")
@ConfigComment("This will teleport players back inside if they toggle the border with a command.")
Expand Down Expand Up @@ -192,4 +207,32 @@ public boolean isReturnTeleportBlock() {
public void setReturnTeleportBlock(boolean returnTeleportBlock) {
this.returnTeleportBlock = returnTeleportBlock;
}

/**
* @return the bounceBack
*/
public boolean isBounceBack() {
return bounceBack;
}

/**
* @param bounceBack the bounceBack to set
*/
public void setBounceBack(boolean bounceBack) {
this.bounceBack = bounceBack;
}

/**
* @return the color
*/
public BorderColor getColor() {
return color;
}

/* *
* @param color the color to set
*/
public void setColor(BorderColor color) {
this.color = color;
}
}
22 changes: 19 additions & 3 deletions src/main/java/world/bentobox/border/listeners/BorderShower.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package world.bentobox.border.listeners;

import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.util.Vector;

import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.util.Util;
import world.bentobox.border.Border;

/**
* A border shower class
Expand Down Expand Up @@ -44,9 +50,19 @@ public default void refreshView(User user, Island island){
}

/**
* Teleports player back within the island space they are in
* @param player player
* Teleports an entity, typically a player back within the island space they are in
* @param entity entity
*/
public void teleportPlayer(Player player);
public default void teleportEntity(Border addon, Entity entity) {
addon.getIslands().getIslandAt(entity.getLocation()).ifPresent(i -> {
Vector unitVector = i.getCenter().toVector().subtract(entity.getLocation().toVector()).normalize()
.multiply(new Vector(1, 0, 1));
// Get distance from border
Location to = entity.getLocation().toVector().add(unitVector).toLocation(entity.getWorld());
to.setPitch(entity.getLocation().getPitch());
to.setYaw(entity.getLocation().getYaw());
Util.teleportAsync(entity, to, TeleportCause.PLUGIN);
});
}

}
83 changes: 76 additions & 7 deletions src/main/java/world/bentobox/border/listeners/PlayerListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
Expand All @@ -22,23 +23,26 @@
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.EntityDismountEvent;
import org.bukkit.event.entity.EntityMountEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.event.vehicle.VehicleMoveEvent;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.NumberConversions;
import org.bukkit.util.RayTraceResult;
import org.bukkit.util.Vector;

import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.events.island.IslandProtectionRangeChangeEvent;
import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.api.metadata.MetaDataValue;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.util.Util;
import world.bentobox.border.Border;
import world.bentobox.border.BorderType;
Expand Down Expand Up @@ -111,7 +115,7 @@ public void onPlayerDamage(EntityDamageEvent e) {
}
Material type = p.getLocation().getBlock().getRelative(BlockFace.DOWN).getType();
if (type == Material.AIR) {
((BorderShower) show).teleportPlayer(p);
((BorderShower) show).teleportEntity(addon, p);
e.setCancelled(true);
}
}
Expand Down Expand Up @@ -204,8 +208,13 @@ public void onPlayerLeaveIsland(PlayerMoveEvent e) {
Util.teleportAsync(p, from).thenRun(() -> inTeleport.remove(p.getUniqueId()));
return;
}
// Backtrack
addon.getIslands().getIslandAt(p.getLocation()).ifPresent(i -> {
// Backtrack - try to find island at current location, or fall back to the player's own island
Optional<Island> optionalIsland = addon.getIslands().getIslandAt(p.getLocation());
if (optionalIsland.isEmpty()) {
optionalIsland = Optional
.ofNullable(addon.getIslands().getIsland(p.getWorld(), User.getInstance(p)));
}
optionalIsland.ifPresent(i -> {
Vector unitVector = i.getProtectionCenter().toVector().subtract(p.getLocation().toVector()).normalize()
.multiply(new Vector(1,0,1));
if (unitVector.lengthSquared() <= 0D) {
Expand Down Expand Up @@ -259,7 +268,10 @@ private boolean outsideCheck(Player player, Location from, Location to) {
|| !user.getMetaData(BorderShower.BORDER_STATE_META_DATA).map(MetaDataValue::asBoolean).orElse(addon.getSettings().isShowByDefault())) {
return false;
}
return addon.getIslands().getIslandAt(to).filter(i -> !i.onIsland(to)).isPresent();
Optional<Island> islandAt = addon.getIslands().getIslandAt(to);
// Player is outside if they are on an island but not within its protection zone,
// or if they are not on any island at all (e.g., pushed out by piston)
return islandAt.isEmpty() || islandAt.filter(i -> !i.onIsland(to)).isPresent();
}

/**
Expand Down Expand Up @@ -338,8 +350,8 @@ public void onVehicleMove(VehicleMoveEvent e) {
// Remove head movement
if (!e.getFrom().toVector().equals(e.getTo().toVector())) {
e.getVehicle().getPassengers().stream().filter(Player.class::isInstance).map(Player.class::cast)
.filter(this::isOn).forEach(p -> addon.getIslands().getIslandAt(p.getLocation())
.ifPresent(i -> show.refreshView(User.getInstance(p), i)));
.filter(this::isOn).forEach(p -> addon.getIslands().getIslandAt(p.getLocation())
.ifPresent(i -> show.refreshView(User.getInstance(p), i)));
}
}

Expand All @@ -357,4 +369,61 @@ public void onProtectionRangeChange(IslandProtectionRangeChangeEvent e) {
}
});
}

/**
* Bounces items back to inside the barrier if thrown by a player
* @param event event
*/
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onItemDrop(PlayerDropItemEvent event) {
if (addon.getSettings().isBounceBack()
&& addon.inGameWorld(event.getPlayer().getWorld())
&& isOn(event.getPlayer())
) {
// Get this island
addon.getIslands().getIslandAt(event.getPlayer().getLocation()).ifPresent(is -> trackItem(event.getItemDrop(), is));
}
}

/**
* Bounces items back to inside the barrier if dropped when a player dies
* @param event event
*/
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerDeath(PlayerDeathEvent event) {
if (addon.getSettings().isBounceBack()
&& addon.inGameWorld(event.getPlayer().getWorld())
&& isOn(event.getPlayer())) {
// Get this island
addon.getIslands().getIslandAt(event.getPlayer().getLocation()).ifPresent(is -> {
event.getDrops().forEach(item -> trackItem(event.getPlayer().getWorld().dropItemNaturally(event.getPlayer().getLocation(), item), is));
event.getDrops().clear(); // We handled them
});
}
}

private void trackItem(Item item, Island island) {
new BukkitRunnable() {
int ticksActive = 0;

@Override
public void run() {
// Stop tracking if the item is picked up, despawned, or 20 seconds have passed
if (!item.isValid() || ticksActive > 400) {
this.cancel();
return;
}

Location loc = item.getLocation();
// Check if the item is going outside the border
if (!island.onIsland(loc)) {
// Reverse the direction
item.setVelocity(item.getVelocity().multiply(-0.5));
this.cancel();
}
ticksActive++;
}
}.runTaskTimer(addon.getPlugin(), 1L, 2L); // Check every 2 ticks (0.1 seconds)
}

}
20 changes: 10 additions & 10 deletions src/main/java/world/bentobox/border/listeners/ShowBarrier.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.util.Vector;

import com.google.common.base.Enums;

import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.metadata.MetaDataValue;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
Expand Down Expand Up @@ -136,7 +136,7 @@ private void showPlayer(Player player, int i, int j, int k, boolean max) {
if (addon.getSettings().isUseBarrierBlocks()
&& player.getLocation().getBlockX() == i
&& player.getLocation().getBlockZ() == k) {
teleportPlayer(player);
teleportEntity(player);
}

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

/**
* Teleport player back within the island space they are in
* @param p player
* @param entity player or entity
*/
public void teleportPlayer(Player p) {
addon.getIslands().getIslandAt(p.getLocation()).ifPresent(i -> {
Vector unitVector = i.getCenter().toVector().subtract(p.getLocation().toVector()).normalize()
public void teleportEntity(Entity entity) {
addon.getIslands().getIslandAt(entity.getLocation()).ifPresent(i -> {
Vector unitVector = i.getCenter().toVector().subtract(entity.getLocation().toVector()).normalize()
.multiply(new Vector(1, 0, 1));
// Get distance from border
Location to = p.getLocation().toVector().add(unitVector).toLocation(p.getWorld());
to.setPitch(p.getLocation().getPitch());
to.setYaw(p.getLocation().getYaw());
Util.teleportAsync(p, to, TeleportCause.PLUGIN);
Location to = entity.getLocation().toVector().add(unitVector).toLocation(entity.getWorld());
to.setPitch(entity.getLocation().getPitch());
to.setYaw(entity.getLocation().getYaw());
Util.teleportAsync(entity, to, TeleportCause.PLUGIN);
});
}

Expand Down
Loading