Makes a whole lot of changes

Adds some new tests
Improves plugin command handling by using one class for each command
Makes some changes to vehicle teleportation to support horses and pigs, but vehicle teleportation is still buggy and messy
Adds some more missing comments
Adds a wildcard permission and uses built-in permissions some places to avoid checking for three different permissions
This commit is contained in:
Kristian Knarvik 2021-02-16 21:58:31 +01:00
parent df074b9ff5
commit 5b7f5649b1
18 changed files with 584 additions and 246 deletions

View File

@ -77,13 +77,17 @@ public class BlockLocation extends Location {
}
/**
* Makes a block location relative to the current location according to given parameters
* @param right <p></p>
* @param depth <p>The y position relative to the current position</p>
* @param distance <p>The distance away from the previous location to the new location</p>
* @param modX <p>x modifier. Defines movement along the x-axis. 0 for no movement</p>
* @param modY <p></p>
* @param modZ <p>z modifier. Defines movement along the z-axis. 0 for no movement</p>
* Makes a block location relative to the current origin according to given parameters
*
* <p>See {@link RelativeBlockVector} to understand better. modX or modZ should always be 0 while the other is 1
* or -1.</p>
*
* @param right <p>The amount of right steps from the top-left origin</p>
* @param depth <p>The amount of downward steps from the top-left origin</p>
* @param distance <p>The distance outward from the top-left origin</p>
* @param modX <p>X modifier. If modX = -1, X will increase as right increases</p>
* @param modY <p>Y modifier. modY = 1 for Y decreasing as depth increases</p>
* @param modZ <p>Z modifier. If modZ = 1, X will increase as distance increases</p>
* @return A new location relative to this block location
*/
public BlockLocation modRelative(int right, int depth, int distance, int modX, int modY, int modZ) {

View File

@ -232,23 +232,27 @@ public class Gate {
return toOwner;
}
public boolean matches(BlockLocation topleft, int modX, int modZ) {
return matches(topleft, modX, modZ, false);
public boolean matches(BlockLocation topLeft, int modX, int modZ) {
return matches(topLeft, modX, modZ, false);
}
public boolean matches(BlockLocation topleft, int modX, int modZ, boolean onCreate) {
public boolean matches(BlockLocation topLeft, int modX, int modZ, boolean onCreate) {
HashMap<Character, Material> portalTypes = new HashMap<>(types);
for (int y = 0; y < layout.length; y++) {
for (int x = 0; x < layout[y].length; x++) {
Character key = layout[y][x];
if (key.equals(ENTRANCE) || key.equals(EXIT)) {
if (Stargate.ignoreEntrance) continue;
if (Stargate.ignoreEntrance) {
continue;
}
Material type = topleft.modRelative(x, y, 0, modX, 1, modZ).getType();
Material type = topLeft.modRelative(x, y, 0, modX, 1, modZ).getType();
// Ignore entrance if it's air and we're creating a new gate
if (onCreate && type == Material.AIR) continue;
if (onCreate && type == Material.AIR) {
continue;
}
if (type != portalBlockClosed && type != portalBlockOpen) {
Stargate.debug("Gate::Matches", "Entrance/Exit Material Mismatch: " + type);
@ -257,9 +261,9 @@ public class Gate {
} else if (!key.equals(ANYTHING)) {
Material id = portalTypes.get(key);
if (id == null) {
portalTypes.put(key, topleft.modRelative(x, y, 0, modX, 1, modZ).getType());
} else if (topleft.modRelative(x, y, 0, modX, 1, modZ).getType() != id) {
Stargate.debug("Gate::Matches", "Block Type Mismatch: " + topleft.modRelative(x, y, 0, modX, 1, modZ).getType() + " != " + id);
portalTypes.put(key, topLeft.modRelative(x, y, 0, modX, 1, modZ).getType());
} else if (topLeft.modRelative(x, y, 0, modX, 1, modZ).getType() != id) {
Stargate.debug("Gate::Matches", "Block Type Mismatch: " + topLeft.modRelative(x, y, 0, modX, 1, modZ).getType() + " != " + id);
return false;
}
}

View File

@ -15,16 +15,16 @@ import org.bukkit.block.Sign;
import org.bukkit.block.data.Bisected;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Powerable;
import org.bukkit.entity.Boat;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Vehicle;
import org.bukkit.entity.minecart.StorageMinecart;
import org.bukkit.entity.minecart.RideableMinecart;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.UUID;
@ -287,7 +287,7 @@ public class Portal {
public Portal getDestination(Player player) {
if (isRandom()) {
destinations = PortalHandler.getDestinations(player, getNetwork());
destinations = PortalHandler.getDestinations(this, player, getNetwork());
if (destinations.size() == 0) {
return null;
}
@ -464,6 +464,10 @@ public class Portal {
return (player != null) && (player.getName().equalsIgnoreCase(this.player.getName()));
}
/**
* Gets whether this portal points to a fixed exit portal
* @return <p>True if this portal points to a fixed exit portal</p>
*/
public boolean isFixed() {
return fixed;
}
@ -482,27 +486,34 @@ public class Portal {
return false;
}
/**
* Teleports a player to this portal
* @param player <p>The player to teleport</p>
* @param origin <p>The portal the player teleports from</p>
* @param event <p>The player move event triggering the event</p>
*/
public void teleport(Player player, Portal origin, PlayerMoveEvent event) {
Location traveller = player.getLocation();
Location exit = getExit(traveller);
Location exit = getExit(player, traveller);
// Handle backwards gates
//Rotate the player to face out from the portal
int adjust = 180;
if (isBackwards() != origin.isBackwards())
if (isBackwards() != origin.isBackwards()) {
adjust = 0;
}
exit.setYaw(traveller.getYaw() - origin.getRotation() + this.getRotation() + adjust);
// Call the StargatePortalEvent to allow plugins to change destination
if (!origin.equals(this)) {
StargatePortalEvent pEvent = new StargatePortalEvent(player, origin, this, exit);
Stargate.server.getPluginManager().callEvent(pEvent);
StargatePortalEvent stargatePortalEvent = new StargatePortalEvent(player, origin, this, exit);
Stargate.server.getPluginManager().callEvent(stargatePortalEvent);
// Teleport is cancelled
if (pEvent.isCancelled()) {
if (stargatePortalEvent.isCancelled()) {
origin.teleport(player, origin, event);
return;
}
// Update exit if needed
exit = pEvent.getExit();
exit = stargatePortalEvent.getExit();
}
// If no event is passed in, assume it's a teleport, and act as such
@ -515,10 +526,15 @@ public class Portal {
}
}
/**
* Teleports a vehicle to this portal
* @param vehicle <p>The vehicle to teleport</p>
*/
public void teleport(final Vehicle vehicle) {
Location traveller = new Location(this.world, vehicle.getLocation().getX(), vehicle.getLocation().getY(),
vehicle.getLocation().getZ());
Location exit = getExit(traveller);
Stargate.log.info(Stargate.getString("prefix") + "Location of vehicle is " + traveller);
Location exit = getExit(vehicle, traveller);
double velocity = vehicle.getVelocity().length();
@ -535,62 +551,95 @@ public class Portal {
Stargate.log.warning(Stargate.getString("prefix") + "Unable to get the world to teleport the vehicle to");
return;
}
Vehicle mineCart = vehicleWorld.spawn(exit, vehicle.getClass());
if (!passengers.isEmpty()) {
final Entity passenger = passengers.get(0);
vehicle.eject();
vehicle.remove();
passenger.eject();
passenger.teleport(exit);
Stargate.server.getScheduler().scheduleSyncDelayedTask(Stargate.stargate, () -> {
mineCart.addPassenger(passenger);
mineCart.setVelocity(newVelocity);
}, 1);
} else {
if (mineCart instanceof StorageMinecart) {
StorageMinecart storageMinecart = (StorageMinecart) mineCart;
storageMinecart.getInventory().setContents(((StorageMinecart) vehicle).getInventory().getContents());
if (vehicle instanceof RideableMinecart || vehicle instanceof Boat) {
putPlayerInNewVehicle(vehicle, passengers, vehicleWorld, exit, newVelocity);
return;
}
Stargate.log.info(Stargate.getString("prefix") + "Teleported minecart to " + mineCart.getLocation());
vehicle.remove();
vehicle.eject();
handleVehiclePassengers(vehicle, passengers, vehicle, exit);
vehicle.teleport(exit);
Stargate.server.getScheduler().scheduleSyncDelayedTask(Stargate.stargate, () -> vehicle.setVelocity(newVelocity), 3);
} else {
Stargate.log.info(Stargate.getString("prefix") + "Teleported vehicle to " + exit);
vehicle.teleport(exit);
Stargate.server.getScheduler().scheduleSyncDelayedTask(Stargate.stargate, () -> {
mineCart.setVelocity(newVelocity);
vehicle.setVelocity(newVelocity);
}, 1);
}
}
public Location getExit(Location traveller) {
Location loc = null;
private void putPlayerInNewVehicle(Vehicle vehicle, List<Entity> passengers, World vehicleWorld, Location exit, Vector newVelocity) {
Vehicle newVehicle = vehicleWorld.spawn(exit, vehicle.getClass());
vehicle.eject();
vehicle.remove();
handleVehiclePassengers(vehicle, passengers, newVehicle, exit);
Stargate.server.getScheduler().scheduleSyncDelayedTask(Stargate.stargate, () -> newVehicle.setVelocity(newVelocity), 1);
}
private void handleVehiclePassengers(Vehicle sourceVehicle, List<Entity> passengers, Vehicle targetVehicle, Location exit) {
for (Entity passenger : passengers) {
passenger.eject();
Stargate.log.info("Teleporting passenger" + passenger + " to " + exit);
if (!passenger.teleport(exit)) {
Stargate.log.info("Failed to teleport passenger");
}
Stargate.server.getScheduler().scheduleSyncDelayedTask(Stargate.stargate, () -> targetVehicle.addPassenger(passenger), 1);
}
}
/**
* Gets the exit location for a given entity and current location
* @param entity <p>The entity to teleport (used to determine distance from portal to avoid suffocation)</p>
* @param traveller <p>The location of the entity travelling</p>
* @return <p>The location the entity should be teleported to.</p>
*/
public Location getExit(Entity entity, Location traveller) {
Location exitLocation = null;
// Check if the gate has an exit block
if (gate.getExit() != null) {
BlockLocation exit = getBlockAt(gate.getExit());
int back = (isBackwards()) ? -1 : 1;
loc = exit.modRelativeLoc(0D, 0D, 1D, traveller.getYaw(), traveller.getPitch(), modX * back, 1, modZ * back);
double entitySize = Math.ceil((float) Math.max(entity.getBoundingBox().getWidthX(), entity.getBoundingBox().getWidthZ()));
exitLocation = exit.modRelativeLoc(0D, 0D, entitySize, traveller.getYaw(), traveller.getPitch(), modX * back, 1, modZ * back);
} else {
Stargate.log.log(Level.WARNING, Stargate.getString("prefix") + "Missing destination point in .gate file " + gate.getFilename());
}
if (loc != null) {
BlockData bd = getWorld().getBlockAt(loc).getBlockData();
if (bd instanceof Bisected && ((Bisected) bd).getHalf() == Bisected.Half.BOTTOM) {
loc.add(0, 0.5, 0);
if (exitLocation != null) {
//Prevent traveller from spawning inside a slab
BlockData blockData = getWorld().getBlockAt(exitLocation).getBlockData();
if (blockData instanceof Bisected && ((Bisected) blockData).getHalf() == Bisected.Half.BOTTOM) {
exitLocation.add(0, 0.5, 0);
}
loc.setPitch(traveller.getPitch());
return loc;
exitLocation.setPitch(traveller.getPitch());
return exitLocation;
} else {
Stargate.log.log(Level.WARNING, Stargate.getString("prefix") + "Unable to generate exit location");
}
return traveller;
}
/**
* Checks whether the chunk the portal is located at is loaded
* @return <p>True if the chunk containing the portal is loaded</p>
*/
public boolean isChunkLoaded() {
//TODO: Improve this in the case where the portal sits between two chunks
return getWorld().isChunkLoaded(topLeft.getBlock().getChunk());
}
/**
* Gets the identity (sign) location of the portal
* @return <p>The identity location of the portal</p>
*/
public BlockLocation getId() {
return this.id;
}
public int getModX() {
return this.modX;
}
@ -603,10 +652,18 @@ public class Portal {
return this.rotX;
}
/**
* Gets the location of the top-left block of the portal
* @return <p>The location of the top-left portal block</p>
*/
public BlockLocation getTopLeft() {
return this.topLeft;
}
/**
* Verifies that all control blocks in this portal follows its gate template
* @return <p>True if all control blocks were verified</p>
*/
public boolean isVerified() {
verified = true;
if (!Stargate.verifyPortals) {
@ -618,6 +675,10 @@ public class Portal {
return verified;
}
/**
* Gets the result of the last portal verification
* @return <p>True if this portal was verified</p>
*/
public boolean wasVerified() {
if (!Stargate.verifyPortals) {
return true;
@ -625,6 +686,10 @@ public class Portal {
return verified;
}
/**
* Checks if all blocks in a gate matches the gate template
* @return <p>True if all blocks match the gate template</p>
*/
public boolean checkIntegrity() {
if (!Stargate.verifyPortals) {
return true;
@ -632,13 +697,18 @@ public class Portal {
return gate.matches(topLeft, modX, modZ);
}
/**
* Activates this portal for the given player
* @param player <p>The player to activate the portal for</p>
* @return <p>True if the portal was activated</p>
*/
public boolean activate(Player player) {
destinations.clear();
destination = "";
Stargate.activeList.add(this);
activePlayer = player;
String network = getNetwork();
destinations = PortalHandler.getDestinations(player, network);
destinations = PortalHandler.getDestinations(this, player, network);
if (Stargate.sortLists) {
Collections.sort(destinations);
}
@ -658,10 +728,15 @@ public class Portal {
return true;
}
/**
* Deactivates this portal
*/
public void deactivate() {
StargateDeactivateEvent event = new StargateDeactivateEvent(this);
Stargate.server.getPluginManager().callEvent(event);
if (event.isCancelled()) return;
if (event.isCancelled()) {
return;
}
Stargate.activeList.remove(this);
if (isFixed()) {
@ -810,6 +885,11 @@ public class Portal {
sign.update();
}
/**
* Gets the block at a relative block vector location
* @param vector <p>The relative block vector</p>
* @return <p>The block at the given relative position</p>
*/
BlockLocation getBlockAt(RelativeBlockVector vector) {
return topLeft.modRelative(vector.getRight(), vector.getDepth(), vector.getDistance(), modX, 1, modZ);
}

View File

@ -44,30 +44,44 @@ public class PortalHandler {
/**
* Gets all destinations in the network viewable by the given player
* @param entrancePortal <p>The portal the user is entering from</p>
* @param player <p>The player who wants to see destinations</p>
* @param network <p>The network to get destinations from</p>
* @return <p>All destinations the player can go to</p>
*/
public static ArrayList<String> getDestinations(Player player, String network) {
public static ArrayList<String> getDestinations(Portal entrancePortal, Player player, String network) {
ArrayList<String> destinations = new ArrayList<>();
for (String dest : allPortalsNet.get(network.toLowerCase())) {
Portal portal = getByName(dest, network);
if (portal == null) continue;
// Check if dest is a random gate
if (portal.isRandom()) continue;
// Check if dest is always open (Don't show if so)
if (portal.isAlwaysOn() && !portal.isShown()) continue;
// Check if dest is this portal
if (dest.equalsIgnoreCase(portal.getName())) continue;
// Check if dest is a fixed gate not pointing to this gate
if (portal.isFixed() && !portal.getDestinationName().equalsIgnoreCase(portal.getName())) continue;
for (String destination : allPortalsNet.get(network.toLowerCase())) {
Portal portal = getByName(destination, network);
if (portal == null) {
continue;
}
// Check if destination is a random gate
if (portal.isRandom()) {
continue;
}
// Check if destination is always open (Don't show if so)
if (portal.isAlwaysOn() && !portal.isShown()) {
continue;
}
// Check if destination is this portal
if (destination.equalsIgnoreCase(entrancePortal.getName())) {
continue;
}
// Check if destination is a fixed gate not pointing to this gate
if (portal.isFixed() && !portal.getDestinationName().equalsIgnoreCase(entrancePortal.getName())) {
continue;
}
// Allow random use by non-players (Minecarts)
if (player == null) {
destinations.add(portal.getName());
continue;
}
// Check if this player can access the dest world
if (!Stargate.canAccessWorld(player, portal.getWorld().getName())) continue;
if (!Stargate.canAccessWorld(player, portal.getWorld().getName())) {
Stargate.log.info("cannot access world");
continue;
}
// Visible to this player.
if (Stargate.canSee(player, portal)) {
destinations.add(portal.getName());
@ -81,7 +95,7 @@ public class PortalHandler {
* @param portal <p>The portal to un-register</p>
* @param removeAll <p>Whether to remove the portal from the list of all portals</p>
*/
public static void unregister(Portal portal, boolean removeAll) {
public static void unregisterPortal(Portal portal, boolean removeAll) {
Stargate.debug("Unregister", "Unregistering gate " + portal.getName());
portal.close(true);
@ -136,7 +150,7 @@ public class PortalHandler {
* Registers a portal
* @param portal <p>The portal to register</p>
*/
static void register(Portal portal) {
private static void registerPortal(Portal portal) {
portal.setFixed(portal.getDestinationName().length() > 0 || portal.isRandom() || portal.isBungee());
// Bungee gates are stored in their own list
@ -200,15 +214,15 @@ public class PortalHandler {
}
BlockLocation parent = new BlockLocation(player.getWorld(), idParent.getX(), idParent.getY(), idParent.getZ());
BlockLocation topleft = null;
BlockLocation topLeft = null;
String name = filterName(event.getLine(0));
String destName = filterName(event.getLine(1));
String destinationName = filterName(event.getLine(1));
String network = filterName(event.getLine(2));
String options = filterName(event.getLine(3)).toLowerCase();
boolean hidden = (options.indexOf('h') != -1);
boolean alwaysOn = (options.indexOf('a') != -1);
boolean priv = (options.indexOf('p') != -1);
boolean isPrivate = (options.indexOf('p') != -1);
boolean free = (options.indexOf('f') != -1);
boolean backwards = (options.indexOf('b') != -1);
boolean show = (options.indexOf('s') != -1);
@ -223,8 +237,8 @@ public class PortalHandler {
if (alwaysOn && !Stargate.canOption(player, "alwayson")) {
alwaysOn = false;
}
if (priv && !Stargate.canOption(player, "private")) {
priv = false;
if (isPrivate && !Stargate.canOption(player, "private")) {
isPrivate = false;
}
if (free && !Stargate.canOption(player, "free")) {
free = false;
@ -243,7 +257,7 @@ public class PortalHandler {
}
// Can not create a non-fixed always-on gate.
if (alwaysOn && destName.length() == 0) {
if (alwaysOn && destinationName.length() == 0) {
alwaysOn = false;
}
@ -268,24 +282,24 @@ public class PortalHandler {
int modX = 0;
int modZ = 0;
float rotX = 0f;
BlockFace buttonfacing = BlockFace.DOWN;
BlockFace buttonFacing = BlockFace.DOWN;
if (idParent.getX() > id.getBlock().getX()) {
modZ -= 1;
rotX = 90f;
buttonfacing = BlockFace.WEST;
buttonFacing = BlockFace.WEST;
} else if (idParent.getX() < id.getBlock().getX()) {
modZ += 1;
rotX = 270f;
buttonfacing = BlockFace.EAST;
buttonFacing = BlockFace.EAST;
} else if (idParent.getZ() > id.getBlock().getZ()) {
modX += 1;
rotX = 180f;
buttonfacing = BlockFace.NORTH;
buttonFacing = BlockFace.NORTH;
} else if (idParent.getZ() < id.getBlock().getZ()) {
modX -= 1;
rotX = 0f;
buttonfacing = BlockFace.SOUTH;
buttonFacing = BlockFace.SOUTH;
}
Gate[] possibleGates = Gate.getGatesByControlBlock(idParent);
@ -305,7 +319,7 @@ public class PortalHandler {
if (gate == null) {
if (possibility.matches(tl, modX, modZ, true)) {
gate = possibility;
topleft = tl;
topLeft = tl;
if (otherControl != null) {
buttonVector = otherControl;
@ -333,14 +347,14 @@ public class PortalHandler {
} else if (!Stargate.hasPerm(player, "stargate.admin.bungee")) {
Stargate.sendMessage(player, Stargate.getString("bungeeDeny"));
return null;
} else if (destName.isEmpty() || network.isEmpty()) {
} else if (destinationName.isEmpty() || network.isEmpty()) {
Stargate.sendMessage(player, Stargate.getString("bungeeEmpty"));
return null;
}
}
// Debug
Stargate.debug("createPortal", "h = " + hidden + " a = " + alwaysOn + " p = " + priv + " f = " + free + " b = " + backwards + " s = " + show + " n = " + noNetwork + " r = " + random + " u = " + bungee);
Stargate.debug("createPortal", "h = " + hidden + " a = " + alwaysOn + " p = " + isPrivate + " f = " + free + " b = " + backwards + " s = " + show + " n = " + noNetwork + " r = " + random + " u = " + bungee);
if (!bungee && (network.length() < 1 || network.length() > 11)) {
network = Stargate.getDefaultNetwork();
@ -375,8 +389,8 @@ public class PortalHandler {
}
// Check if the user can create gates to this world.
if (!bungee && !deny && destName.length() > 0) {
Portal p = getByName(destName, network);
if (!bungee && !deny && destinationName.length() > 0) {
Portal p = getByName(destinationName, network);
if (p != null) {
String world = p.getWorld().getName();
if (!Stargate.canAccessWorld(player, world)) {
@ -389,7 +403,7 @@ public class PortalHandler {
// Bleh, gotta check to make sure none of this gate belongs to another gate. Boo slow.
for (RelativeBlockVector v : gate.getBorder()) {
BlockLocation b = topleft.modRelative(v.getRight(), v.getDepth(), v.getDistance(), modX, 1, modZ);
BlockLocation b = topLeft.modRelative(v.getRight(), v.getDepth(), v.getDistance(), modX, 1, modZ);
if (getByBlock(b.getBlock()) != null) {
Stargate.debug("createPortal", "Gate conflicts with existing gate");
Stargate.sendMessage(player, Stargate.getString("createConflict"));
@ -399,7 +413,7 @@ public class PortalHandler {
BlockLocation button = null;
Portal portal;
portal = new Portal(topleft, modX, modZ, rotX, id, button, destName, name, false, network, gate, player.getUniqueId(), player.getName(), hidden, alwaysOn, priv, free, backwards, show, noNetwork, random, bungee);
portal = new Portal(topLeft, modX, modZ, rotX, id, button, destinationName, name, false, network, gate, player.getUniqueId(), player.getName(), hidden, alwaysOn, isPrivate, free, backwards, show, noNetwork, random, bungee);
int cost = Stargate.getCreateCost(player, gate);
@ -456,20 +470,20 @@ public class PortalHandler {
// No button on an always-open gate.
if (!alwaysOn) {
button = topleft.modRelative(buttonVector.getRight(), buttonVector.getDepth(), buttonVector.getDistance() + 1, modX, 1, modZ);
button = topLeft.modRelative(buttonVector.getRight(), buttonVector.getDepth(), buttonVector.getDistance() + 1, modX, 1, modZ);
Directional buttondata = (Directional) Bukkit.createBlockData(gate.getButton());
buttondata.setFacing(buttonfacing);
buttondata.setFacing(buttonFacing);
button.getBlock().setBlockData(buttondata);
portal.setButton(button);
}
register(portal);
registerPortal(portal);
portal.drawSign();
// Open always on gate
if (portal.isRandom() || portal.isBungee()) {
portal.open(true);
} else if (portal.isAlwaysOn()) {
Portal dest = getByName(destName, portal.getNetwork());
Portal dest = getByName(destinationName, portal.getNetwork());
if (dest != null) {
portal.open(true);
dest.drawSign();
@ -757,7 +771,7 @@ public class PortalHandler {
gate, ownerUUID, ownerName);
loadPortalOptions(portal, portalData);
register(portal);
registerPortal(portal);
portal.close(true);
}
scanner.close();
@ -835,7 +849,7 @@ public class PortalHandler {
Stargate.debug("loadAllGates", "Control Block Type == " + portal.getBlockAt(control).getBlock().getType().name());
}
}
PortalHandler.unregister(portal, false);
PortalHandler.unregisterPortal(portal, false);
Stargate.log.info(Stargate.getString("prefix") + "Destroying stargate at " + portal.toString());
}

View File

@ -1,9 +1,12 @@
package net.knarcraft.stargate;
/**
* This stores a block location as a vector in an alternate coordinate system
* This stores a block location as a vector relative to a position
*
* <p></p>
* <p>A relative block vector stores a vector relative to some origin. The origin in this plugin is usually the
* top-left block of a gate. The right is therefore the distance from the top-left corner towards the top-right corner.
* Depth is the distance from the top-left corner to the bottom-left corner. Distance is the distance outward from the
* gate.</p>
*/
public class RelativeBlockVector {
@ -13,9 +16,9 @@ public class RelativeBlockVector {
/**
* Instantiates a new relative block vector
* @param right <p>The x coordinate in the gate description</p>
* @param depth <p>The y coordinate in the gate description</p>
* @param distance <p></p>
* @param right <p>The distance to the right relative to the origin</p>
* @param depth <p>The distance downward relative to the origin</p>
* @param distance <p>The distance outward relative to the origin</p>
*/
public RelativeBlockVector(int right, int depth, int distance) {
this.right = right;
@ -23,14 +26,26 @@ public class RelativeBlockVector {
this.distance = distance;
}
/**
* Gets the distance to the right relative to the origin
* @return The distance to the right relative to the origin
*/
public int getRight() {
return right;
}
/**
* Gets the distance downward relative to the origin
* @return The distance downward relative to the origin
*/
public int getDepth() {
return depth;
}
/**
* Gets the distance outward relative to the origin
* @return The distance outward relative to the origin
*/
public int getDistance() {
return distance;
}

View File

@ -1,5 +1,7 @@
package net.knarcraft.stargate;
import net.knarcraft.stargate.command.CommandStarGate;
import net.knarcraft.stargate.command.StarGateTabCompleter;
import net.knarcraft.stargate.event.StargateAccessEvent;
import net.knarcraft.stargate.listener.BlockEventListener;
import net.knarcraft.stargate.listener.BungeeCordListener;
@ -15,8 +17,8 @@ import org.bukkit.ChatColor;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.block.Sign;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
@ -24,7 +26,6 @@ import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.java.JavaPluginLoader;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.HashMap;
@ -45,7 +46,9 @@ public class Stargate extends JavaPlugin {
private PluginManager pm;
public static Server server;
public static Stargate stargate;
private static LanguageLoader languageLoader;
public static LanguageLoader languageLoader;
private static String pluginVersion;
private static String portalFolder;
private static String gateFolder;
@ -109,7 +112,7 @@ public class Stargate extends JavaPlugin {
@Override
public void onEnable() {
PluginDescriptionFile pdfFile = this.getDescription();
PluginDescriptionFile pluginDescriptionFile = this.getDescription();
pm = getServer().getPluginManager();
newConfig = this.getConfig();
log = Logger.getLogger("Minecraft");
@ -122,7 +125,9 @@ public class Stargate extends JavaPlugin {
gateFolder = dataFolderPath + "/gates/";
langFolder = dataFolderPath + "/lang/";
log.info(pdfFile.getName() + " v." + pdfFile.getVersion() + " is enabled.");
pluginVersion = pluginDescriptionFile.getVersion();
log.info(pluginDescriptionFile.getName() + " v." + pluginDescriptionFile.getVersion() + " is enabled.");
// Register events before loading gates to stop weird things happening.
pm.registerEvents(new PlayerEventsListener(), this);
@ -159,6 +164,20 @@ public class Stargate extends JavaPlugin {
getServer().getScheduler().scheduleSyncRepeatingTask(this, new StarGateThread(), 0L, 100L);
getServer().getScheduler().scheduleSyncRepeatingTask(this, new BlockPopulatorThread(), 0L, 1L);
this.registerCommands();
}
private void registerCommands() {
PluginCommand stargateCommand = this.getCommand("stargate");
if (stargateCommand != null) {
stargateCommand.setExecutor(new CommandStarGate(this));
stargateCommand.setTabCompleter(new StarGateTabCompleter());
}
}
public static String getPluginVersion() {
return pluginVersion;
}
public static boolean destroyedByExplosion() {
@ -421,6 +440,26 @@ public class Stargate extends JavaPlugin {
return !event.getDeny();
}
/**
* Checks whether a given user can travel between two portals
* @param player <p>The player to check</p>
* @param entrancePortal <p>The portal the user wants to enter</p>
* @param destination <p>The portal the user wants to exit</p>
* @return <p>True if the user is allowed to access the portal</p>
*/
public static boolean canAccessPortal(Player player, Portal entrancePortal, Portal destination) {
boolean deny = false;
// Check if player has access to this server for Bungee gates
if (entrancePortal.isBungee() && !Stargate.canAccessServer(player, entrancePortal.getNetwork())) {
deny = true;
} else if (!Stargate.canAccessNetwork(player, entrancePortal.getNetwork())) {
deny = true;
} else if (!Stargate.canAccessWorld(player, destination.getWorld().getName())) {
deny = true;
}
return Stargate.canAccessPortal(player, entrancePortal, deny);
}
/*
* Return true if the portal is free for the player
*/
@ -634,26 +673,11 @@ public class Stargate extends JavaPlugin {
return input.replace(search, value);
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
String cmd = command.getName();
if (cmd.equalsIgnoreCase("sg")) {
if (args.length != 1) return false;
if (args[0].equalsIgnoreCase("about")) {
sender.sendMessage("stargate Plugin created by Drakia");
if (!languageLoader.getString("author").isEmpty())
sender.sendMessage("Language created by " + languageLoader.getString("author"));
return true;
}
if (sender instanceof Player) {
Player p = (Player) sender;
if (!hasPerm(p, "stargate.admin") && !hasPerm(p, "stargate.admin.reload")) {
sendMessage(sender, "Permission Denied");
return true;
}
}
if (args[0].equalsIgnoreCase("reload")) {
/**
* Reloads all portals and files
* @param sender <p>The sender of the reload request</p>
*/
public void reload(CommandSender sender) {
// Deactivate portals
for (Portal p : activeList) {
p.deactivate();
@ -703,11 +727,6 @@ public class Stargate extends JavaPlugin {
}
sendMessage(sender, "stargate reloaded");
return true;
}
return false;
}
return false;
}
}

View File

@ -0,0 +1,26 @@
package net.knarcraft.stargate.command;
import net.knarcraft.stargate.Stargate;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
/**
* This command represents the plugin's about command
*/
public class CommandAbout implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
@NotNull String[] strings) {
commandSender.sendMessage(ChatColor.GOLD + "Stargate Plugin created by " + ChatColor.GREEN + "Drakia");
String author = Stargate.languageLoader.getString("author");
if (!author.isEmpty())
commandSender.sendMessage(ChatColor.GOLD + "Language created by " + ChatColor.GREEN + author);
return true;
}
}

View File

@ -0,0 +1,39 @@
package net.knarcraft.stargate.command;
import net.knarcraft.stargate.Stargate;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* This command represents the plugin's reload command
*/
public class CommandReload implements CommandExecutor {
private Stargate plugin;
/**
* Instantiates the reload command
* @param plugin <p>A reference to the calling plugin object</p>
*/
public CommandReload(Stargate plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
@NotNull String[] strings) {
if (commandSender instanceof Player) {
Player player = (Player) commandSender;
if (!player.hasPermission("stargate.reload")) {
Stargate.sendMessage(commandSender, "Permission Denied");
return true;
}
}
plugin.reload(commandSender);
return true;
}
}

View File

@ -0,0 +1,43 @@
package net.knarcraft.stargate.command;
import net.knarcraft.stargate.Stargate;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
/**
* This command represents any command which starts with stargate
*
* <p>This prefix command should only be used for commands which are certain to collide with others and which relate to
* the plugin itself, not commands for functions of the plugin.</p>
*/
public class CommandStarGate implements CommandExecutor {
private Stargate plugin;
/**
* Instantiates the stargate command
* @param plugin <p>A reference to the calling plugin object</p>
*/
public CommandStarGate(Stargate plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
@NotNull String[] strings) {
if (strings.length > 0) {
if (strings[0].equalsIgnoreCase("about")) {
return new CommandAbout().onCommand(commandSender, command, s, strings);
} else if (strings[0].equalsIgnoreCase("reload")) {
return new CommandReload(plugin).onCommand(commandSender, command, s, strings);
}
return false;
} else {
commandSender.sendMessage(ChatColor.GOLD + "Stargate version " + ChatColor.GREEN + Stargate.getPluginVersion());
return true;
}
}
}

View File

@ -0,0 +1,23 @@
package net.knarcraft.stargate.command;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class StarGateTabCompleter implements TabCompleter {
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command,
@NotNull String s, @NotNull String[] strings) {
List<String> commands = new ArrayList<>();
commands.add("about");
commands.add("reload");
return commands;
}
}

View File

@ -107,7 +107,7 @@ public class BlockEventListener implements Listener {
return;
}
PortalHandler.unregister(portal, true);
PortalHandler.unregisterPortal(portal, true);
Stargate.sendMessage(player, Stargate.getString("destroyMsg"), false);
}

View File

@ -20,8 +20,12 @@ public class EntityEventListener implements Listener {
* This event handler prevents sending entities to the normal nether instead of the stargate target
* @param event <p>The event to check and possibly cancel</p>
*/
@EventHandler(priority = EventPriority.HIGHEST)
@EventHandler(priority = EventPriority.LOWEST)
public void onPortalEvent(EntityPortalEvent event) {
if (event.isCancelled()) {
return;
}
Portal portal = PortalHandler.getByAdjacentEntrance(event.getFrom());
if (portal != null) {
event.setCancelled(true);
@ -47,7 +51,7 @@ public class EntityEventListener implements Listener {
continue;
}
if (Stargate.destroyedByExplosion()) {
PortalHandler.unregister(portal, true);
PortalHandler.unregisterPortal(portal, true);
} else {
event.setCancelled(true);
break;

View File

@ -9,7 +9,9 @@ import org.bukkit.GameMode;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.data.type.WallSign;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Vehicle;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@ -22,6 +24,7 @@ import org.bukkit.event.player.PlayerTeleportEvent;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Objects;
public class PlayerEventsListener implements Listener {
@ -52,12 +55,25 @@ public class PlayerEventsListener implements Listener {
public void onPlayerTeleport(PlayerTeleportEvent event) {
// cancel portal and endgateway teleportation if it's from a stargate entrance
PlayerTeleportEvent.TeleportCause cause = event.getCause();
if (!event.isCancelled()
&& (cause == PlayerTeleportEvent.TeleportCause.NETHER_PORTAL
|| cause == PlayerTeleportEvent.TeleportCause.END_GATEWAY && World.Environment.THE_END == event.getFrom().getWorld().getEnvironment())
if (!event.isCancelled() && (cause == PlayerTeleportEvent.TeleportCause.NETHER_PORTAL
|| cause == PlayerTeleportEvent.TeleportCause.END_GATEWAY && World.Environment.THE_END ==
Objects.requireNonNull(event.getFrom().getWorld()).getEnvironment())
&& PortalHandler.getByAdjacentEntrance(event.getFrom()) != null) {
event.setCancelled(true);
}
if (event.isCancelled()) {
return;
}
Entity playerVehicle = event.getPlayer().getVehicle();
Portal portal = PortalHandler.getByEntrance(event.getFrom());
if (playerVehicle != null && PortalHandler.getByEntrance(event.getFrom()) != null) {
Portal destinationPortal = portal.getDestination();
if (destinationPortal != null) {
VehicleEventListener.teleportVehicleAfterPlayer((Vehicle) playerVehicle, destinationPortal, event.getPlayer());
Stargate.log.info("Player was driving " + playerVehicle.getName());
}
}
}
@EventHandler
@ -65,53 +81,40 @@ public class PlayerEventsListener implements Listener {
if (event.isCancelled()) return;
// Check to see if the player actually moved
if (event.getFrom().getBlockX() == event.getTo().getBlockX() && event.getFrom().getBlockY() == event.getTo().getBlockY() && event.getFrom().getBlockZ() == event.getTo().getBlockZ()) {
if (event.getFrom().getBlockX() == event.getTo().getBlockX() && event.getFrom().getBlockY() ==
event.getTo().getBlockY() && event.getFrom().getBlockZ() == event.getTo().getBlockZ()) {
return;
}
Player player = event.getPlayer();
Portal entracePortal = PortalHandler.getByEntrance(event.getTo());
Portal entrancePortal = PortalHandler.getByEntrance(event.getTo());
// No portal or not open
if (entracePortal == null || !entracePortal.isOpen()) return;
if (entrancePortal == null || !entrancePortal.isOpen()) {
return;
}
// Not open for this player
if (!entracePortal.isOpenFor(player)) {
if (!entrancePortal.isOpenFor(player)) {
Stargate.sendMessage(player, Stargate.getString("denyMsg"));
entracePortal.teleport(player, entracePortal, event);
entrancePortal.teleport(player, entrancePortal, event);
return;
}
Portal destination = entracePortal.getDestination(player);
if (!entracePortal.isBungee() && destination == null) return;
boolean deny = false;
// Check if player has access to this server for Bungee gates
if (entracePortal.isBungee()) {
if (!Stargate.canAccessServer(player, entracePortal.getNetwork())) {
deny = true;
}
} else {
// Check if player has access to this network
if (!Stargate.canAccessNetwork(player, entracePortal.getNetwork())) {
deny = true;
}
// Check if player has access to destination world
if (!Stargate.canAccessWorld(player, destination.getWorld().getName())) {
deny = true;
}
}
if (!Stargate.canAccessPortal(player, entracePortal, deny)) {
Stargate.sendMessage(player, Stargate.getString("denyMsg"));
entracePortal.teleport(player, entracePortal, event);
entracePortal.close(false);
Portal destination = entrancePortal.getDestination(player);
if (!entrancePortal.isBungee() && destination == null) {
return;
}
int cost = Stargate.getUseCost(player, entracePortal, destination);
if (!Stargate.canAccessPortal(player, entrancePortal, destination)) {
Stargate.sendMessage(player, Stargate.getString("denyMsg"));
entrancePortal.teleport(player, entrancePortal, event);
entrancePortal.close(false);
return;
}
int cost = Stargate.getUseCost(player, entrancePortal, destination);
if (cost > 0) {
if (!EconomyHelper.payTeleportFee(entracePortal, player, cost)) {
if (!EconomyHelper.payTeleportFee(entrancePortal, player, cost)) {
return;
}
}
@ -119,25 +122,25 @@ public class PlayerEventsListener implements Listener {
Stargate.sendMessage(player, Stargate.getString("teleportMsg"), false);
// BungeeCord Support
if (entracePortal.isBungee()) {
if (entrancePortal.isBungee()) {
if (!Stargate.enableBungee) {
player.sendMessage(Stargate.getString("bungeeDisabled"));
entracePortal.close(false);
entrancePortal.close(false);
return;
}
// Teleport the player back to this gate, for sanity's sake
entracePortal.teleport(player, entracePortal, event);
entrancePortal.teleport(player, entrancePortal, event);
// Send the SGBungee packet first, it will be queued by BC if required
try {
// Build the message, format is <player>#@#<destination>
String msg = event.getPlayer().getName() + "#@#" + entracePortal.getDestinationName();
String msg = event.getPlayer().getName() + "#@#" + entrancePortal.getDestinationName();
// Build the message data, sent over the SGBungee bungeecord channel
ByteArrayOutputStream bao = new ByteArrayOutputStream();
DataOutputStream msgData = new DataOutputStream(bao);
msgData.writeUTF("Forward");
msgData.writeUTF(entracePortal.getNetwork()); // Server
msgData.writeUTF(entrancePortal.getNetwork()); // Server
msgData.writeUTF("SGBungee"); // Channel
msgData.writeShort(msg.length()); // Data Length
msgData.writeBytes(msg); // Data
@ -153,7 +156,7 @@ public class PlayerEventsListener implements Listener {
ByteArrayOutputStream bao = new ByteArrayOutputStream();
DataOutputStream msgData = new DataOutputStream(bao);
msgData.writeUTF("Connect");
msgData.writeUTF(entracePortal.getNetwork());
msgData.writeUTF(entrancePortal.getNetwork());
player.sendPluginMessage(Stargate.stargate, "BungeeCord", bao.toByteArray());
bao.reset();
@ -164,12 +167,12 @@ public class PlayerEventsListener implements Listener {
}
// Close portal if required (Should never be)
entracePortal.close(false);
entrancePortal.close(false);
return;
}
destination.teleport(player, entracePortal, event);
entracePortal.close(false);
destination.teleport(player, entrancePortal, event);
entrancePortal.close(false);
}
@EventHandler

View File

@ -35,11 +35,39 @@ public class VehicleEventListener implements Listener {
return;
}
//TODO: As there are a lot of vehicles in the game now, a lot needs to be accounted for to make this work as expected
teleportVehicle(passengers, entrancePortal, vehicle);
}
public static void teleportVehicleAfterPlayer(Vehicle vehicle, Portal destinationPortal, Player player) {
destinationPortal.teleport(vehicle);
Stargate.server.getScheduler().scheduleSyncDelayedTask(Stargate.stargate, () -> vehicle.addPassenger(player), 6);
}
/**
* Teleports a vehicle through a stargate
* @param passengers <p>The passengers inside the vehicle</p>
* @param entrancePortal <p>The portal the vehicle is entering</p>
* @param vehicle <p>The vehicle passing through</p>
*/
public static void teleportVehicle(List<Entity> passengers, Portal entrancePortal, Vehicle vehicle) {
teleportVehicle(passengers, entrancePortal, vehicle, false);
}
/**
* Teleports a vehicle through a stargate
* @param passengers <p>The passengers inside the vehicle</p>
* @param entrancePortal <p>The portal the vehicle is entering</p>
* @param vehicle <p>The vehicle passing through</p>
* @param skipOpenCheck <p>Skips the check for whether the portal is open for the player</p>
*/
public static void teleportVehicle(List<Entity> passengers, Portal entrancePortal, Vehicle vehicle, boolean skipOpenCheck) {
if (!passengers.isEmpty() && passengers.get(0) instanceof Player) {
Stargate.log.info(Stargate.getString("prefox") + "Found passenger minecart");
teleportPlayerAndVehicle(entrancePortal, vehicle, passengers);
Stargate.log.info(Stargate.getString("prefox") + "Found passenger vehicle");
teleportPlayerAndVehicle(entrancePortal, vehicle, passengers, skipOpenCheck);
} else {
Stargate.log.info(Stargate.getString("prefox") + "Found empty minecart");
Stargate.log.info(Stargate.getString("prefox") + "Found empty vehicle");
Portal destinationPortal = entrancePortal.getDestination();
if (destinationPortal == null) {
Stargate.log.warning(Stargate.getString("prefox") + "Unable to find portal destination");
@ -50,14 +78,15 @@ public class VehicleEventListener implements Listener {
}
/**
* Teleports a player and the minecart the player sits in
* Teleports a player and the vehicle the player sits in
* @param entrancePortal <p>The portal the minecart entered</p>
* @param vehicle <p>The vehicle to teleport</p>
* @param passengers <p>Any entities sitting in the minecart</p>
*/
private void teleportPlayerAndVehicle(Portal entrancePortal, Vehicle vehicle, List<Entity> passengers) {
private static void teleportPlayerAndVehicle(Portal entrancePortal, Vehicle vehicle, List<Entity> passengers,
boolean skipOpenCheck) {
Player player = (Player) passengers.get(0);
if (!entrancePortal.isOpenFor(player)) {
if (!skipOpenCheck && !entrancePortal.isOpenFor(player)) {
Stargate.sendMessage(player, Stargate.getString("denyMsg"));
return;
}
@ -66,23 +95,15 @@ public class VehicleEventListener implements Listener {
if (destinationPortal == null) {
return;
}
boolean deny = false;
// Check if player has access to this network
if (!Stargate.canAccessNetwork(player, entrancePortal.getNetwork())) {
deny = true;
}
// Check if player has access to destination world
if (!Stargate.canAccessWorld(player, destinationPortal.getWorld().getName())) {
deny = true;
}
if (!Stargate.canAccessPortal(player, entrancePortal, deny)) {
//Make sure the user can access the portal
if (!Stargate.canAccessPortal(player, entrancePortal, destinationPortal)) {
Stargate.sendMessage(player, Stargate.getString("denyMsg"));
entrancePortal.close(false);
return;
}
//Transfer payment if necessary
int cost = Stargate.getUseCost(player, entrancePortal, destinationPortal);
if (cost > 0) {
if (!EconomyHelper.payTeleportFee(entrancePortal, player, cost)) {

View File

@ -1,6 +1,5 @@
package net.knarcraft.stargate.listener;
import net.knarcraft.stargate.Portal;
import net.knarcraft.stargate.PortalHandler;
import net.knarcraft.stargate.Stargate;
import org.bukkit.World;

View File

@ -8,10 +8,26 @@ website: https://knarcraft.net
api-version: 1.16
softdepend: [Vault]
commands:
sg:
description: Used to reload the plugin. Console use only.
usage: /<command> reload - Used to reload the plugin. Console use only.
stargate:
aliases:
- sg
description: Used to see stargate info
usage: /<command> <reload/about> - Used to see stargate info or reload the plugin
permissions:
stargate.*:
description: Wildcard permission
default: op
children:
stargate.use: true
stargate.create: true
stargate.destroy: true
stargate.free: true
stargate.option: true
stargate.admin: true
stargate.reload: true
stargate.reload:
description: Allows reloading the plugin
default: false
stargate.use:
description: Allow use of all gates linking to any world in any network
default: true
@ -30,3 +46,5 @@ permissions:
stargate.admin:
description: Allow all admin features (Hidden/Private only so far)
default: op
children:
stargate.reload: true

View File

@ -81,4 +81,13 @@ public class BlockLocationTest {
assertEquals("56,87,34", location.toString());
}
@Test
public void modRelativeTest() {
BlockLocation location = new BlockLocation(mockWorld, 5, 5, 5);
BlockLocation relativeLocation = location.modRelative(4, 2, 1, -1, 1, 0);
assertEquals(9, relativeLocation.getBlockX());
assertEquals(3, relativeLocation.getBlockY());
assertEquals(6, relativeLocation.getBlockZ());
}
}

View File

@ -0,0 +1,17 @@
package net.knarcraft.stargate;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class RelativeBlockVectorTest {
@Test
public void getTest() {
RelativeBlockVector relativeBlockVector = new RelativeBlockVector(56, 44, 23);
assertEquals(56, relativeBlockVector.getRight());
assertEquals(44, relativeBlockVector.getDepth());
assertEquals(23, relativeBlockVector.getDistance());
}
}