Compare commits

..

9 Commits

Author SHA1 Message Date
24ef1cde02 Bumps version for release
All checks were successful
EpicKnarvik97/Stargate/pipeline/head This commit looks good
2026-01-24 17:23:23 +01:00
9b28107db8 Adds changes to README
All checks were successful
EpicKnarvik97/Stargate/pipeline/head This commit looks good
2026-01-24 17:22:50 +01:00
99c3b611dc Stops measuring distances across worlds
All checks were successful
EpicKnarvik97/Stargate/pipeline/head This commit looks good
2026-01-23 13:33:18 +01:00
07463f77d9 Blocks 1-block END_GATEWAY teleportation events which prevented sneaking from triggering a teleportation
All checks were successful
EpicKnarvik97/Stargate/pipeline/head This commit looks good
2026-01-23 13:18:02 +01:00
bbb5c5184e Stops cancelling END_GATEWAY teleportation events, as those prevented teleportation from end gateways
All checks were successful
EpicKnarvik97/Stargate/pipeline/head This commit looks good
2026-01-23 12:51:16 +01:00
69e334c195 Actually outputs the teleportation failure error message
All checks were successful
EpicKnarvik97/Stargate/pipeline/head This commit looks good
2026-01-23 02:24:59 +01:00
3e0b38c3d0 Removes SimpleVectorOperation and adds a different message for a failed teleportation
All checks were successful
EpicKnarvik97/Stargate/pipeline/head This commit looks good
2026-01-23 02:23:12 +01:00
2bf9f13379 Fixes a bug when checking whether a player has the required permission to access a world
All checks were successful
EpicKnarvik97/Stargate/pipeline/head This commit looks good
2026-01-23 02:21:18 +01:00
89a68b40b1 Moves config loaded toggle to avoid unnecessary debug output 2026-01-23 02:20:41 +01:00
40 changed files with 554 additions and 930 deletions

View File

@@ -31,7 +31,7 @@ Highly capable, simple to use, with robust network capabilities and extensive cu
- LockedCraft and LittleBigBug also forked that version to add underwater and tag support, as well as a few bug fixes. - LockedCraft and LittleBigBug also forked that version to add underwater and tag support, as well as a few bug fixes.
- This version is a combination of all the forks above, maintained by EpicKnarvik97. - This version is a combination of all the forks above, maintained by EpicKnarvik97.
- A rewrite was underway, but because of a mix of real life obligations, and a general lack of motivation, progress - A rewrite was underway, but because of a mix of real life obligations, and a general lack of motivation, progress
stopped. stopped. Some features/improvements have found its way from the rewrite to this version over time.
## License ## License
@@ -489,6 +489,7 @@ Please note that %variableName% should be kept, as it will be replaced with a re
|-----------------------|--------------------------------------------------------------------| |-----------------------|--------------------------------------------------------------------|
| prefix | \[Stargate] | | prefix | \[Stargate] |
| teleportMsg | Teleported | | teleportMsg | Teleported |
| teleportationFailed | Teleportation was cancelled or denied |
| destroyMsg | Gate Destroyed | | destroyMsg | Gate Destroyed |
| invalidMsg | Invalid Destination | | invalidMsg | Invalid Destination |
| blockMsg | Destination Blocked | | blockMsg | Destination Blocked |
@@ -535,6 +536,25 @@ Please note that %variableName% should be kept, as it will be replaced with a re
# Changes # Changes
#### \[Version 0.11.5.12] Unified Legacy Fork
- Fixes gate verification incorrectly treating valid Stargates as invalid
- Improves the default permissions of players to allow personal creation of standard nether stargates, and general
Stargate use.
- Adds three new permission groups for easier permission setup: stargate.group.admin, stargate.group.builder,
stargate.group.player. The builder group allows creation and destruction of all Stargates, and usage of all
options/flags except bungee portals.
- Fixes end gateways not teleporting players unless sneaking into the portal on newer Minecraft versions.
- Adds an error message in case Stargate detects some other plugin cancelled or interfered with its teleportation.
- Stops some debug output during startup when debug is disabled
- Renames the silent option to quiet internally to better match the Q character used to enable the option.
- Replaces code for message formatting
- Improves some error messages
- Replaces some code with KnarLib implementations
- Updates some dependencies
- Restructures all event code, and improves Stargate protection
- Removes static permission strings, and removes redundancy in permission checking code
#### \[Version 0.11.5.11] Unified Legacy Fork #### \[Version 0.11.5.11] Unified Legacy Fork
- Removes legacy sign drawing code, as the check for whether a server supported the sign sides kept failing for some - Removes legacy sign drawing code, as the check for whether a server supported the sign sides kept failing for some
@@ -545,7 +565,7 @@ Please note that %variableName% should be kept, as it will be replaced with a re
#### \[Version 0.11.5.10] Unified Legacy Fork #### \[Version 0.11.5.10] Unified Legacy Fork
- Fixed a problem with material tag support - Fixed a problem with material tag support
- Made serveral optimisations to significantly improve performance on servers with high playercounts. - Made serveral optimisations to significantly improve performance on servers with high player counts.
#### \[Version 0.11.5.9] Unified Legacy Fork #### \[Version 0.11.5.9] Unified Legacy Fork
@@ -571,7 +591,7 @@ Please note that %variableName% should be kept, as it will be replaced with a re
- Fixed a potential stack trace experienced when disabling Dynmap - Fixed a potential stack trace experienced when disabling Dynmap
- Fixed some problems related to negative economy transactions. - Fixed some problems related to negative economy transactions.
- Fixed an exception occuring when negative yaw values are encountered. - Fixed an exception occurring when negative yaw values are encountered.
- Updated the about command and added a debug command. - Updated the about command and added a debug command.
#### \[Version 0.11.5.5] Unified Legacy Fork #### \[Version 0.11.5.5] Unified Legacy Fork

View File

@@ -4,7 +4,7 @@
<groupId>net.knarcraft</groupId> <groupId>net.knarcraft</groupId>
<artifactId>Stargate</artifactId> <artifactId>Stargate</artifactId>
<version>0.11.5.12-SNAPSHOT</version> <version>0.11.5.12</version>
<licenses> <licenses>
<license> <license>

View File

@@ -20,13 +20,13 @@ import net.knarcraft.stargate.listener.PlayerEventListener;
import net.knarcraft.stargate.listener.StargateBreakListener; import net.knarcraft.stargate.listener.StargateBreakListener;
import net.knarcraft.stargate.listener.StargateCreateDestroyListener; import net.knarcraft.stargate.listener.StargateCreateDestroyListener;
import net.knarcraft.stargate.listener.StargateTeleportListener; import net.knarcraft.stargate.listener.StargateTeleportListener;
import net.knarcraft.stargate.portal.PortalHandler;
import net.knarcraft.stargate.portal.PortalRegistry; import net.knarcraft.stargate.portal.PortalRegistry;
import net.knarcraft.stargate.thread.BlockChangeThread; import net.knarcraft.stargate.thread.BlockChangeThread;
import net.knarcraft.stargate.thread.ChunkUnloadThread; import net.knarcraft.stargate.thread.ChunkUnloadThread;
import net.knarcraft.stargate.thread.ControlBlocksUpdateThread; import net.knarcraft.stargate.thread.ControlBlocksUpdateThread;
import net.knarcraft.stargate.thread.StarGateThread; import net.knarcraft.stargate.thread.StarGateThread;
import net.knarcraft.stargate.utility.BStatsHelper; import net.knarcraft.stargate.utility.BStatsHelper;
import net.knarcraft.stargate.utility.PortalUtil;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.PluginManager;
@@ -336,7 +336,7 @@ public class Stargate extends ConfigCommentPlugin {
@Override @Override
public void onDisable() { public void onDisable() {
PortalUtil.closeAllPortals(); PortalHandler.closeAllPortals();
PortalRegistry.clearPortals(); PortalRegistry.clearPortals();
if (stargateConfig != null) { if (stargateConfig != null) {
stargateConfig.clearManagedWorlds(); stargateConfig.clearManagedWorlds();

View File

@@ -12,12 +12,12 @@ import net.knarcraft.stargate.config.formatting.Message;
import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.config.formatting.SGFormatBuilder;
import net.knarcraft.stargate.container.BlockChangeRequest; import net.knarcraft.stargate.container.BlockChangeRequest;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.portal.PortalHandler;
import net.knarcraft.stargate.portal.PortalRegistry; import net.knarcraft.stargate.portal.PortalRegistry;
import net.knarcraft.stargate.portal.property.gate.GateHandler; import net.knarcraft.stargate.portal.property.gate.GateHandler;
import net.knarcraft.stargate.thread.BlockChangeThread; import net.knarcraft.stargate.thread.BlockChangeThread;
import net.knarcraft.stargate.utility.BungeeHelper; import net.knarcraft.stargate.utility.BungeeHelper;
import net.knarcraft.stargate.utility.PortalFileHelper; import net.knarcraft.stargate.utility.PortalFileHelper;
import net.knarcraft.stargate.utility.PortalUtil;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@@ -92,6 +92,7 @@ public final class StargateConfig {
*/ */
public void finishSetup() { public void finishSetup() {
this.loadConfig(); this.loadConfig();
this.isLoaded = true;
//Enable the required channels for Bungee support //Enable the required channels for Bungee support
if (stargateGateConfig.enableBungee()) { if (stargateGateConfig.enableBungee()) {
@@ -133,8 +134,6 @@ public final class StargateConfig {
"integration is disabled."); "integration is disabled.");
DynmapManager.disable(); DynmapManager.disable();
} }
this.isLoaded = true;
} }
/** /**
@@ -284,7 +283,7 @@ public final class StargateConfig {
} }
//Force all portals to close //Force all portals to close
closeAllOpenPortals(); closeAllOpenPortals();
PortalUtil.closeAllPortals(); PortalHandler.closeAllPortals();
//Clear queues and lists //Clear queues and lists
activePortalsQueue.clear(); activePortalsQueue.clear();

View File

@@ -74,7 +74,7 @@ public final class DynmapManager {
if (markerSet == null || Stargate.getStargateConfig().isDynmapDisabled()) { if (markerSet == null || Stargate.getStargateConfig().isDynmapDisabled()) {
return; return;
} }
World world = portal.getLocation().getWorld(); World world = portal.getWorld();
if (portal.getOptions().isHidden() || world == null) { if (portal.getOptions().isHidden() || world == null) {
return; return;
} }
@@ -82,7 +82,7 @@ public final class DynmapManager {
Location location; Location location;
@Nullable RelativeBlockVector exit = portal.getGate().getLayout().getExit(); @Nullable RelativeBlockVector exit = portal.getGate().getLayout().getExit();
if (exit == null) { if (exit == null) {
location = portal.getLocation().getTopLeft(); location = portal.getTopLeft();
} else { } else {
location = portal.getBlockAt(exit); location = portal.getBlockAt(exit);
} }

View File

@@ -202,6 +202,11 @@ public enum Message {
* The author that created the loaded translation * The author that created the loaded translation
*/ */
AUTHOR("author"), AUTHOR("author"),
/**
* The error message to display when a teleportation fails for whatever reason
*/
TELEPORTATION_FAILED("teleportationFailed"),
; ;
private final String key; private final String key;

View File

@@ -2,7 +2,6 @@ package net.knarcraft.stargate.container;
import org.bukkit.Axis; import org.bukkit.Axis;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -11,7 +10,7 @@ import org.jetbrains.annotations.Nullable;
*/ */
public class BlockChangeRequest { public class BlockChangeRequest {
private final Block blockLocation; private final BlockLocation blockLocation;
private final Material newMaterial; private final Material newMaterial;
private final Axis newAxis; private final Axis newAxis;
@@ -22,7 +21,7 @@ public class BlockChangeRequest {
* @param material <p>The new material to change the block to</p> * @param material <p>The new material to change the block to</p>
* @param axis <p>The new axis to orient the block along</p> * @param axis <p>The new axis to orient the block along</p>
*/ */
public BlockChangeRequest(@NotNull Block blockLocation, @NotNull Material material, @Nullable Axis axis) { public BlockChangeRequest(@NotNull BlockLocation blockLocation, @NotNull Material material, @Nullable Axis axis) {
this.blockLocation = blockLocation; this.blockLocation = blockLocation;
newMaterial = material; newMaterial = material;
newAxis = axis; newAxis = axis;
@@ -34,7 +33,7 @@ public class BlockChangeRequest {
* @return <p>The location of the block</p> * @return <p>The location of the block</p>
*/ */
@NotNull @NotNull
public Block getBlockLocation() { public BlockLocation getBlockLocation() {
return blockLocation; return blockLocation;
} }

View File

@@ -5,6 +5,10 @@ import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Directional;
import org.bukkit.block.data.type.Sign;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -18,6 +22,8 @@ import org.jetbrains.annotations.Nullable;
*/ */
public class BlockLocation extends Location { public class BlockLocation extends Location {
private BlockLocation parent = null;
/** /**
* Creates a new block location * Creates a new block location
* *
@@ -142,6 +148,50 @@ public class BlockLocation extends Location {
return this.clone(); return this.clone();
} }
/**
* Gets this block location's parent block
*
* <p>The parent block is the block the item at this block location is attached to. Usually this is the block a
* sign or wall sign is attached to.</p>
*
* @return <p>This block location's parent block</p>
*/
@Nullable
public Block getParent() {
if (parent == null) {
findParent();
}
if (parent == null) {
return null;
}
return parent.getBlock();
}
/**
* Tries to find the parent block location
*
* <p>If this block location is a sign, the parent is the block location of the block the sign is connected to.</p>
*/
private void findParent() {
int offsetX = 0;
int offsetY = 0;
int offsetZ = 0;
BlockData blockData = getBlock().getBlockData();
if (blockData instanceof Directional) {
//Get the offset of the block "behind" this block
BlockFace facing = ((Directional) blockData).getFacing().getOppositeFace();
offsetX = facing.getModX();
offsetZ = facing.getModZ();
} else if (blockData instanceof Sign) {
//Get offset the block beneath the sign
offsetY = -1;
} else {
return;
}
parent = this.makeRelativeBlockLocation(offsetX, offsetY, offsetZ);
}
@Override @Override
@NotNull @NotNull
public String toString() { public String toString() {

View File

@@ -1,6 +1,5 @@
package net.knarcraft.stargate.container; package net.knarcraft.stargate.container;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -22,28 +21,6 @@ import org.jetbrains.annotations.Nullable;
*/ */
public record RelativeBlockVector(int right, int down, int out) { public record RelativeBlockVector(int right, int down, int out) {
/**
* Adds the given value to this relative block vector's "right" property
*
* @param valueToAdd <p>The value to add</p>
* @return <p>The new resulting vector</p>
*/
@NotNull
public RelativeBlockVector addRight(int valueToAdd) {
return new RelativeBlockVector(this.right + valueToAdd, this.down, this.out);
}
/**
* Adds the given value to this relative block vector's "down" property
*
* @param valueToAdd <p>The value to add</p>
* @return <p>The new resulting vector</p>
*/
@NotNull
public RelativeBlockVector addDown(int valueToAdd) {
return new RelativeBlockVector(this.right, this.down + valueToAdd, this.out);
}
/** /**
* Adds the given value to this relative block vector's "out" property * Adds the given value to this relative block vector's "out" property
* *
@@ -55,15 +32,6 @@ public record RelativeBlockVector(int right, int down, int out) {
return new RelativeBlockVector(this.right, this.down, this.out + valueToAdd); return new RelativeBlockVector(this.right, this.down, this.out + valueToAdd);
} }
/**
* Gets a relative vector in the real space representing this relative block vector
*
* @return <p>A vector representing this relative block vector</p>
*/
public Vector toVector() {
return new Vector(this.right, -this.down, this.out);
}
/** /**
* Gets a relative block vector which is this inverted (pointing in the opposite direction) * Gets a relative block vector which is this inverted (pointing in the opposite direction)
* *

View File

@@ -8,11 +8,11 @@ import net.knarcraft.stargate.config.formatting.Message;
import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.config.formatting.SGFormatBuilder;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.portal.PortalActivator; import net.knarcraft.stargate.portal.PortalActivator;
import net.knarcraft.stargate.portal.PortalHandler;
import net.knarcraft.stargate.portal.teleporter.PlayerTeleporter; import net.knarcraft.stargate.portal.teleporter.PlayerTeleporter;
import net.knarcraft.stargate.utility.BungeeHelper; import net.knarcraft.stargate.utility.BungeeHelper;
import net.knarcraft.stargate.utility.MaterialHelper; import net.knarcraft.stargate.utility.MaterialHelper;
import net.knarcraft.stargate.utility.PermissionHelper; import net.knarcraft.stargate.utility.PermissionHelper;
import net.knarcraft.stargate.utility.PortalUtil;
import net.knarcraft.stargate.utility.UUIDMigrationHelper; import net.knarcraft.stargate.utility.UUIDMigrationHelper;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@@ -70,7 +70,7 @@ public class PlayerEventListener implements Listener {
return; return;
} }
Portal portal = PortalUtil.getBungeePortal(destination); Portal portal = PortalHandler.getBungeePortal(destination);
if (portal == null) { if (portal == null) {
Stargate.debug("PlayerJoin", "Error fetching destination portal: " + destination); Stargate.debug("PlayerJoin", "Error fetching destination portal: " + destination);
return; return;
@@ -115,7 +115,7 @@ public class PlayerEventListener implements Listener {
*/ */
private void handleSignClick(@NotNull PlayerInteractEvent event, @NotNull Player player, @NotNull Block block, private void handleSignClick(@NotNull PlayerInteractEvent event, @NotNull Player player, @NotNull Block block,
boolean leftClick) { boolean leftClick) {
Portal portal = PortalUtil.getByBlock(block); Portal portal = PortalHandler.getByBlock(block);
if (portal == null) { if (portal == null) {
return; return;
} }
@@ -225,7 +225,7 @@ public class PlayerEventListener implements Listener {
} }
if (MaterialHelper.isButtonCompatible(block.getType())) { if (MaterialHelper.isButtonCompatible(block.getType())) {
Portal portal = PortalUtil.getByBlock(block); Portal portal = PortalHandler.getByBlock(block);
if (portal == null) { if (portal == null) {
return; return;
} }
@@ -261,7 +261,7 @@ public class PlayerEventListener implements Listener {
* @param player <p>The player that clicked the block</p> * @param player <p>The player that clicked the block</p>
*/ */
private void displayPortalInfo(@NotNull Block block, @NotNull Player player) { private void displayPortalInfo(@NotNull Block block, @NotNull Player player) {
Portal portal = PortalUtil.getByBlock(block); Portal portal = PortalHandler.getByBlock(block);
if (portal == null) { if (portal == null) {
return; return;
} }

View File

@@ -2,8 +2,8 @@ package net.knarcraft.stargate.listener;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.portal.PortalHandler;
import net.knarcraft.stargate.portal.PortalRegistry; import net.knarcraft.stargate.portal.PortalRegistry;
import net.knarcraft.stargate.utility.PortalUtil;
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;
@@ -56,7 +56,7 @@ public class StargateBreakListener implements Listener {
return; return;
} }
Block block = event.getBlock(); Block block = event.getBlock();
Portal portal = PortalUtil.getByEntrance(block); Portal portal = PortalHandler.getByEntrance(block);
if (portal != null) { if (portal != null) {
//Prevent blocks from being placed in the entrance, if protectEntrance is enabled, as breaking the block //Prevent blocks from being placed in the entrance, if protectEntrance is enabled, as breaking the block
// would destroy the portal // would destroy the portal
@@ -75,7 +75,7 @@ public class StargateBreakListener implements Listener {
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onEntityExplode(@NotNull EntityExplodeEvent event) { public void onEntityExplode(@NotNull EntityExplodeEvent event) {
for (Block block : event.blockList()) { for (Block block : event.blockList()) {
Portal portal = PortalUtil.getByBlock(block); Portal portal = PortalHandler.getByBlock(block);
if (portal == null) { if (portal == null) {
continue; continue;
} }
@@ -92,7 +92,7 @@ public class StargateBreakListener implements Listener {
public void onCreatureSpawn(@NotNull CreatureSpawnEvent event) { public void onCreatureSpawn(@NotNull CreatureSpawnEvent event) {
//Prevent Zombified Piglins and other creatures form spawning at stargates //Prevent Zombified Piglins and other creatures form spawning at stargates
if (event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.NETHER_PORTAL && if (event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.NETHER_PORTAL &&
PortalUtil.getByEntrance(event.getLocation()) != null) { PortalHandler.getByEntrance(event.getLocation()) != null) {
event.setCancelled(true); event.setCancelled(true);
Stargate.debug("EntitySpawnListener", "Prevented creature from spawning at Stargate"); Stargate.debug("EntitySpawnListener", "Prevented creature from spawning at Stargate");
} }
@@ -213,8 +213,8 @@ public class StargateBreakListener implements Listener {
* @param block <p>The block in question</p> * @param block <p>The block in question</p>
*/ */
private boolean cancelIfAtEntrance(@NotNull Cancellable event, @NotNull Block block) { private boolean cancelIfAtEntrance(@NotNull Cancellable event, @NotNull Block block) {
if (PortalUtil.getByEntrance(block) != null || PortalUtil.getByControl(block) != null || if (PortalHandler.getByEntrance(block) != null || PortalHandler.getByControl(block) != null ||
PortalUtil.getByBlock(block) != null) { PortalHandler.getByBlock(block) != null) {
event.setCancelled(true); event.setCancelled(true);
return true; return true;
} else { } else {

View File

@@ -8,11 +8,11 @@ import net.knarcraft.stargate.container.BlockLocation;
import net.knarcraft.stargate.event.StargateDestroyEvent; import net.knarcraft.stargate.event.StargateDestroyEvent;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.portal.PortalCreator; import net.knarcraft.stargate.portal.PortalCreator;
import net.knarcraft.stargate.portal.PortalHandler;
import net.knarcraft.stargate.portal.PortalRegistry; import net.knarcraft.stargate.portal.PortalRegistry;
import net.knarcraft.stargate.utility.EconomyHelper; import net.knarcraft.stargate.utility.EconomyHelper;
import net.knarcraft.stargate.utility.PermissionHelper; import net.knarcraft.stargate.utility.PermissionHelper;
import net.knarcraft.stargate.utility.PortalFileHelper; import net.knarcraft.stargate.utility.PortalFileHelper;
import net.knarcraft.stargate.utility.PortalUtil;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.data.type.WallSign; import org.bukkit.block.data.type.WallSign;
@@ -51,8 +51,8 @@ public class StargateCreateDestroyListener implements Listener {
//Remove the sign if the no sign option is enabled //Remove the sign if the no sign option is enabled
if (portal.getOptions().hasNoSign()) { if (portal.getOptions().hasNoSign()) {
Material replaceMaterial = PortalFileHelper.decideRemovalMaterial(portal.getLocation().getSignBlock(), portal); Material replaceMaterial = PortalFileHelper.decideRemovalMaterial(portal.getSignLocation(), portal);
BlockChangeRequest request = new BlockChangeRequest(portal.getLocation().getSignBlock(), replaceMaterial, null); BlockChangeRequest request = new BlockChangeRequest(portal.getSignLocation(), replaceMaterial, null);
Stargate.addControlBlockUpdateRequest(request); Stargate.addControlBlockUpdateRequest(request);
} }
@@ -73,9 +73,9 @@ public class StargateCreateDestroyListener implements Listener {
Player player = event.getPlayer(); Player player = event.getPlayer();
//Decide if a portal is broken //Decide if a portal is broken
Portal portal = PortalUtil.getByBlock(block); Portal portal = PortalHandler.getByBlock(block);
if (portal == null && Stargate.getGateConfig().protectEntrance()) { if (portal == null && Stargate.getGateConfig().protectEntrance()) {
portal = PortalUtil.getByEntrance(block); portal = PortalHandler.getByEntrance(block);
} }
if (portal == null) { if (portal == null) {
return; return;

View File

@@ -6,6 +6,7 @@ import net.knarcraft.stargate.config.formatting.SGFormatBuilder;
import net.knarcraft.stargate.container.BlockLocation; import net.knarcraft.stargate.container.BlockLocation;
import net.knarcraft.stargate.container.FromTheEndTeleportation; import net.knarcraft.stargate.container.FromTheEndTeleportation;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.portal.PortalHandler;
import net.knarcraft.stargate.portal.teleporter.PlayerTeleporter; import net.knarcraft.stargate.portal.teleporter.PlayerTeleporter;
import net.knarcraft.stargate.portal.teleporter.VehicleTeleporter; import net.knarcraft.stargate.portal.teleporter.VehicleTeleporter;
import net.knarcraft.stargate.utility.BungeeHelper; import net.knarcraft.stargate.utility.BungeeHelper;
@@ -13,7 +14,6 @@ import net.knarcraft.stargate.utility.EconomyHelper;
import net.knarcraft.stargate.utility.EntityHelper; import net.knarcraft.stargate.utility.EntityHelper;
import net.knarcraft.stargate.utility.MaterialHelper; import net.knarcraft.stargate.utility.MaterialHelper;
import net.knarcraft.stargate.utility.PermissionHelper; import net.knarcraft.stargate.utility.PermissionHelper;
import net.knarcraft.stargate.utility.PortalUtil;
import net.knarcraft.stargate.utility.TeleportHelper; import net.knarcraft.stargate.utility.TeleportHelper;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
@@ -63,15 +63,24 @@ public class StargateTeleportListener implements Listener {
* *
* @param event <p>The event to check and possibly cancel</p> * @param event <p>The event to check and possibly cancel</p>
*/ */
@EventHandler @EventHandler(ignoreCancelled = true)
public void onPlayerTeleport(@NotNull PlayerTeleportEvent event) { public void onPlayerTeleport(@NotNull PlayerTeleportEvent event) {
PlayerTeleportEvent.TeleportCause cause = event.getCause(); PlayerTeleportEvent.TeleportCause cause = event.getCause();
//Block normal portal teleportation if teleporting from a stargate //Block normal portal teleportation if teleporting from a stargate
if (!event.isCancelled() && (cause == PlayerTeleportEvent.TeleportCause.NETHER_PORTAL || if ((cause == PlayerTeleportEvent.TeleportCause.NETHER_PORTAL ||
cause == PlayerTeleportEvent.TeleportCause.END_GATEWAY ||
cause == PlayerTeleportEvent.TeleportCause.END_PORTAL) cause == PlayerTeleportEvent.TeleportCause.END_PORTAL)
&& PortalUtil.getByAdjacentEntrance(event.getFrom()) != null) { && PortalHandler.getByAdjacentEntrance(event.getFrom()) != null) {
Stargate.debug("StargateTeleportListener::onPlayerTeleport",
"Cancelled vanilla portal event to " + event.getTo());
event.setCancelled(true);
}
// Cancel end gateway teleportation to the same destination
if (event.getTo() != null && cause == PlayerTeleportEvent.TeleportCause.END_GATEWAY &&
PortalHandler.getByAdjacentEntrance(event.getFrom()) != null &&
event.getFrom().getWorld() != null && event.getFrom().getWorld().equals(event.getTo().getWorld()) &&
event.getFrom().distance(event.getTo()) <= 1) {
event.setCancelled(true); event.setCancelled(true);
} }
} }
@@ -89,7 +98,7 @@ public class StargateTeleportListener implements Listener {
Entity entity = event.getEntity(); Entity entity = event.getEntity();
//Cancel normal portal event is near a stargate //Cancel normal portal event is near a stargate
if (PortalUtil.getByAdjacentEntrance(event.getFrom(), EntityHelper.getEntityMaxSizeInt(entity)) != null) { if (PortalHandler.getByAdjacentEntrance(event.getFrom(), EntityHelper.getEntityMaxSizeInt(entity)) != null) {
event.setCancelled(true); event.setCancelled(true);
} }
} }
@@ -110,9 +119,9 @@ public class StargateTeleportListener implements Listener {
Portal entrancePortal; Portal entrancePortal;
int entitySize = EntityHelper.getEntityMaxSizeInt(vehicle); int entitySize = EntityHelper.getEntityMaxSizeInt(vehicle);
if (EntityHelper.getEntityMaxSize(vehicle) > 1) { if (EntityHelper.getEntityMaxSize(vehicle) > 1) {
entrancePortal = PortalUtil.getByAdjacentEntrance(event.getTo(), entitySize - 1); entrancePortal = PortalHandler.getByAdjacentEntrance(event.getTo(), entitySize - 1);
} else { } else {
entrancePortal = PortalUtil.getByEntrance(event.getTo()); entrancePortal = PortalHandler.getByEntrance(event.getTo());
} }
//Return if the portal cannot be teleported through //Return if the portal cannot be teleported through
@@ -142,10 +151,10 @@ public class StargateTeleportListener implements Listener {
if (!isRelevantMoveEvent(event, player, fromLocation, toLocation)) { if (!isRelevantMoveEvent(event, player, fromLocation, toLocation)) {
return; return;
} }
Portal entrancePortal = PortalUtil.getByEntrance(toLocation); Portal entrancePortal = PortalHandler.getByEntrance(toLocation);
//Check an additional block away in case the portal is a bungee portal using END_PORTAL //Check an additional block away in case the portal is a bungee portal using END_PORTAL
if (entrancePortal == null) { if (entrancePortal == null) {
entrancePortal = PortalUtil.getByAdjacentEntrance(toLocation); entrancePortal = PortalHandler.getByAdjacentEntrance(toLocation);
// This should never realistically be null // This should never realistically be null
if (entrancePortal == null) { if (entrancePortal == null) {
return; return;
@@ -183,7 +192,7 @@ public class StargateTeleportListener implements Listener {
return; return;
} }
Portal portal = PortalUtil.getByAdjacentEntrance(location); Portal portal = PortalHandler.getByAdjacentEntrance(location);
if (portal == null) { if (portal == null) {
return; return;
} }
@@ -258,8 +267,8 @@ public class StargateTeleportListener implements Listener {
Stargate.debug(route, "Unable to find portal destination"); Stargate.debug(route, "Unable to find portal destination");
return; return;
} }
Stargate.debug("vehicleTeleport", destinationPortal.getLocation().getWorld() + " " + Stargate.debug("vehicleTeleport", destinationPortal.getWorld() + " " +
destinationPortal.getLocation().getSignBlock()); destinationPortal.getSignLocation());
new VehicleTeleporter(destinationPortal, vehicle).teleportEntity(entrancePortal); new VehicleTeleporter(destinationPortal, vehicle).teleportEntity(entrancePortal);
} }
} }
@@ -388,6 +397,7 @@ public class StargateTeleportListener implements Listener {
*/ */
private void teleportPlayer(@Nullable Entity playerVehicle, @NotNull Player player, @NotNull Portal entrancePortal, private void teleportPlayer(@Nullable Entity playerVehicle, @NotNull Player player, @NotNull Portal entrancePortal,
@NotNull Portal destination, @NotNull PlayerMoveEvent event) { @NotNull Portal destination, @NotNull PlayerMoveEvent event) {
boolean success = true;
if (playerVehicle instanceof LivingEntity) { if (playerVehicle instanceof LivingEntity) {
//Make sure any horses are properly tamed //Make sure any horses are properly tamed
if (playerVehicle instanceof AbstractHorse horse && !horse.isTamed()) { if (playerVehicle instanceof AbstractHorse horse && !horse.isTamed()) {
@@ -399,10 +409,12 @@ public class StargateTeleportListener implements Listener {
new VehicleTeleporter(destination, (Vehicle) playerVehicle).teleportEntity(entrancePortal); new VehicleTeleporter(destination, (Vehicle) playerVehicle).teleportEntity(entrancePortal);
} else { } else {
//Just teleport the player like normal //Just teleport the player like normal
new PlayerTeleporter(destination, player).teleportPlayer(entrancePortal, event); success = new PlayerTeleporter(destination, player).teleportPlayer(entrancePortal, event);
} }
if (!entrancePortal.getOptions().isQuiet()) { if (success && !entrancePortal.getOptions().isQuiet()) {
new SGFormatBuilder(Message.TELEPORTED).success(player); new SGFormatBuilder(Message.TELEPORTED).success(player);
} else if (!success) {
new SGFormatBuilder(Message.TELEPORTATION_FAILED).error(player);
} }
entrancePortal.getPortalOpener().closePortal(false); entrancePortal.getPortalOpener().closePortal(false);
} }
@@ -461,18 +473,22 @@ public class StargateTeleportListener implements Listener {
* @return <p>The portal the player entered, or null if no portal was entered</p> * @return <p>The portal the player entered, or null if no portal was entered</p>
*/ */
private Portal getEnteredPortal(@NotNull BlockLocation toLocation, @NotNull Player player) { private Portal getEnteredPortal(@NotNull BlockLocation toLocation, @NotNull Player player) {
Portal entrancePortal = PortalUtil.getByEntrance(toLocation); Portal entrancePortal = PortalHandler.getByEntrance(toLocation);
// Return if in an entrance // Return if in an entrance
if (entrancePortal != null) { if (entrancePortal != null) {
Stargate.debug("StargateTeleportListener::getEnteredPortal", "Player entered portal " + entrancePortal);
return entrancePortal; return entrancePortal;
} }
//Check an additional block away for special cases like BungeeCord portals using END_PORTAL as its material //Check an additional block away for special cases like BungeeCord portals using END_PORTAL as its material
entrancePortal = PortalUtil.getByAdjacentEntrance(toLocation); entrancePortal = PortalHandler.getByAdjacentEntrance(toLocation);
if (entrancePortal == null) { if (entrancePortal == null) {
return null; return null;
} }
Stargate.debug("StargateTeleportListener::getEnteredPortal", "Player entered adjacent portal " + entrancePortal);
// If END_GATEWAY and END_PORTAL cannot appear, skip further checks // If END_GATEWAY and END_PORTAL cannot appear, skip further checks
Set<Material> entranceMaterials = MaterialHelper.specifiersToMaterials(entrancePortal.getGate().getPortalOpenMaterials()); Set<Material> entranceMaterials = MaterialHelper.specifiersToMaterials(entrancePortal.getGate().getPortalOpenMaterials());
if (!entranceMaterials.contains(Material.END_GATEWAY) && !entranceMaterials.contains(Material.END_PORTAL)) { if (!entranceMaterials.contains(Material.END_GATEWAY) && !entranceMaterials.contains(Material.END_PORTAL)) {

View File

@@ -1,5 +1,7 @@
package net.knarcraft.stargate.portal; package net.knarcraft.stargate.portal;
import net.knarcraft.stargate.container.BlockLocation;
import net.knarcraft.stargate.container.RelativeBlockVector;
import net.knarcraft.stargate.portal.property.PortalLocation; import net.knarcraft.stargate.portal.property.PortalLocation;
import net.knarcraft.stargate.portal.property.PortalOption; import net.knarcraft.stargate.portal.property.PortalOption;
import net.knarcraft.stargate.portal.property.PortalOptions; import net.knarcraft.stargate.portal.property.PortalOptions;
@@ -8,7 +10,7 @@ import net.knarcraft.stargate.portal.property.PortalStrings;
import net.knarcraft.stargate.portal.property.PortalStructure; import net.knarcraft.stargate.portal.property.PortalStructure;
import net.knarcraft.stargate.portal.property.gate.Gate; import net.knarcraft.stargate.portal.property.gate.Gate;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import org.bukkit.block.Block; import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -45,7 +47,7 @@ public class Portal {
* @param portalOwner <p>The portal's owner</p> * @param portalOwner <p>The portal's owner</p>
* @param options <p>A map containing all possible portal options, with true for the ones enabled</p> * @param options <p>A map containing all possible portal options, with true for the ones enabled</p>
*/ */
public Portal(@NotNull PortalLocation portalLocation, @Nullable Block button, public Portal(@NotNull PortalLocation portalLocation, @Nullable BlockLocation button,
@NotNull PortalStrings portalStrings, @NotNull Gate gate, @NotNull PortalOwner portalOwner, @NotNull PortalStrings portalStrings, @NotNull Gate gate, @NotNull PortalOwner portalOwner,
@NotNull Map<PortalOption, Boolean> options) { @NotNull Map<PortalOption, Boolean> options) {
this.location = portalLocation; this.location = portalLocation;
@@ -261,6 +263,59 @@ public class Portal {
} }
} }
/**
* Gets the world this portal belongs to
*
* @return <p>The world this portal belongs to</p>
*/
@Nullable
public World getWorld() {
return location.getWorld();
}
/**
* Gets the location of this portal's sign
*
* @return <p>The location of this portal's sign</p>
*/
@NotNull
public BlockLocation getSignLocation() {
return this.location.getSignLocation();
}
/**
* Gets the rotation (yaw) of this portal
*
* <p>The yaw is used to calculate all kinds of directions. See DirectionHelper to see how the yaw is used to
* calculate to/from other direction types.</p>
*
* @return <p>The rotation (yaw) of this portal</p>
*/
public float getYaw() {
return this.location.getYaw();
}
/**
* Gets the location of the top-left block of the portal
*
* @return <p>The location of the top-left portal block</p>
*/
@NotNull
public BlockLocation getTopLeft() {
return this.location.getTopLeft();
}
/**
* Gets the block at the given location relative to this portal's top-left block
*
* @param vector <p>The relative block vector explaining the position of the block</p>
* @return <p>The block at the given relative position</p>
*/
@NotNull
public BlockLocation getBlockAt(@NotNull RelativeBlockVector vector) {
return getTopLeft().getRelativeLocation(vector, this.getYaw());
}
/** /**
* Cleans a string by removing color codes, lower-casing and replacing spaces with underscores * Cleans a string by removing color codes, lower-casing and replacing spaces with underscores
* *
@@ -269,14 +324,13 @@ public class Portal {
*/ */
@NotNull @NotNull
public static String cleanString(@NotNull String string) { public static String cleanString(@NotNull String string) {
// TODO: Replace special characters such as : and .
return ChatColor.stripColor(ChatColor.translateAlternateColorCodes('&', string)).toLowerCase(); return ChatColor.stripColor(ChatColor.translateAlternateColorCodes('&', string)).toLowerCase();
} }
@Override @Override
@NotNull @NotNull
public String toString() { public String toString() {
return String.format("Portal [id=%s, network=%s name=%s, type=%s]", this.location.getSignBlock(), network, name, return String.format("Portal [id=%s, network=%s name=%s, type=%s]", getSignLocation(), network, name,
structure.getGate().getFilename()); structure.getGate().getFilename());
} }

View File

@@ -6,7 +6,6 @@ import net.knarcraft.stargate.config.formatting.SGFormatBuilder;
import net.knarcraft.stargate.event.StargateActivateEvent; import net.knarcraft.stargate.event.StargateActivateEvent;
import net.knarcraft.stargate.event.StargateDeactivateEvent; import net.knarcraft.stargate.event.StargateDeactivateEvent;
import net.knarcraft.stargate.utility.ListHelper; import net.knarcraft.stargate.utility.ListHelper;
import net.knarcraft.stargate.utility.PortalUtil;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -75,16 +74,16 @@ public class PortalActivator {
String portalNetwork = portal.getCleanNetwork(); String portalNetwork = portal.getCleanNetwork();
if (portal.getOptions().isRandom()) { if (portal.getOptions().isRandom()) {
//Find possible destinations //Find possible destinations
List<String> destinations = PortalUtil.getDestinations(portal, player, portalNetwork); List<String> destinations = PortalHandler.getDestinations(portal, player, portalNetwork);
if (destinations.isEmpty()) { if (destinations.isEmpty()) {
return null; return null;
} }
//Get one random destination //Get one random destination
String randomDestination = ListHelper.getRandom(destinations); String randomDestination = ListHelper.getRandom(destinations);
return PortalUtil.getByName(randomDestination, portalNetwork); return PortalHandler.getByName(randomDestination, portalNetwork);
} else { } else {
//Just return the normal fixed destination //Just return the normal fixed destination
return PortalUtil.getByName(destination, portalNetwork); return PortalHandler.getByName(destination, portalNetwork);
} }
} }
@@ -147,7 +146,7 @@ public class PortalActivator {
activePlayer = player; activePlayer = player;
String network = portal.getCleanNetwork(); String network = portal.getCleanNetwork();
destinations = PortalUtil.getDestinations(portal, player, network); destinations = PortalHandler.getDestinations(portal, player, network);
//Sort destinations if enabled //Sort destinations if enabled
if (Stargate.getGateConfig().sortNetworkDestinations()) { if (Stargate.getGateConfig().sortNetworkDestinations()) {
@@ -251,7 +250,7 @@ public class PortalActivator {
} }
activate = true; activate = true;
List<String> portalsInNetwork = PortalUtil.getNetwork(portal.getCleanNetwork()); List<String> portalsInNetwork = PortalHandler.getNetwork(portal.getCleanNetwork());
if (portalsInNetwork != null) { if (portalsInNetwork != null) {
Stargate.debug("cycleDestination", "Network Size: " + portalsInNetwork.size()); Stargate.debug("cycleDestination", "Network Size: " + portalsInNetwork.size());
} }

View File

@@ -3,6 +3,8 @@ package net.knarcraft.stargate.portal;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.config.formatting.Message; import net.knarcraft.stargate.config.formatting.Message;
import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.config.formatting.SGFormatBuilder;
import net.knarcraft.stargate.container.BlockLocation;
import net.knarcraft.stargate.container.RelativeBlockVector;
import net.knarcraft.stargate.event.StargateCreateEvent; import net.knarcraft.stargate.event.StargateCreateEvent;
import net.knarcraft.stargate.portal.property.PortalLocation; import net.knarcraft.stargate.portal.property.PortalLocation;
import net.knarcraft.stargate.portal.property.PortalOption; import net.knarcraft.stargate.portal.property.PortalOption;
@@ -17,13 +19,11 @@ import net.knarcraft.stargate.utility.ListHelper;
import net.knarcraft.stargate.utility.MaterialHelper; import net.knarcraft.stargate.utility.MaterialHelper;
import net.knarcraft.stargate.utility.PermissionHelper; import net.knarcraft.stargate.utility.PermissionHelper;
import net.knarcraft.stargate.utility.PortalFileHelper; import net.knarcraft.stargate.utility.PortalFileHelper;
import net.knarcraft.stargate.utility.PortalUtil;
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.BlockFace;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.block.SignChangeEvent; import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.util.BlockVector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -60,8 +60,8 @@ public class PortalCreator {
@Nullable @Nullable
public Portal createPortal() { public Portal createPortal() {
String route = "PortalCreator::createPortal"; String route = "PortalCreator::createPortal";
Block signLocation = event.getBlock(); BlockLocation signLocation = new BlockLocation(event.getBlock());
Block signControlBlock = DirectionHelper.getParent(signLocation); Block signControlBlock = signLocation.getParent();
//Return early if the sign is not placed on a block, or the block is not a control block //Return early if the sign is not placed on a block, or the block is not a control block
if (signControlBlock == null || GateHandler.getGatesByControlBlock(signControlBlock).isEmpty()) { if (signControlBlock == null || GateHandler.getGatesByControlBlock(signControlBlock).isEmpty()) {
@@ -70,51 +70,50 @@ public class PortalCreator {
} }
//The control block is already part of another portal //The control block is already part of another portal
if (PortalUtil.getByBlock(signControlBlock) != null) { if (PortalHandler.getByBlock(signControlBlock) != null) {
Stargate.debug(route, "idParent belongs to existing stargate"); Stargate.debug(route, "idParent belongs to existing stargate");
return null; return null;
} }
//Get necessary information from the gate's sign //Get necessary information from the gate's sign
@NotNull String portalName = PortalUtil.filterName(event.getLine(0)); @NotNull String portalName = PortalHandler.filterName(event.getLine(0));
@NotNull String destinationName = PortalUtil.filterName(event.getLine(1)); @NotNull String destinationName = PortalHandler.filterName(event.getLine(1));
@NotNull String network = PortalUtil.filterName(event.getLine(2)); @NotNull String network = PortalHandler.filterName(event.getLine(2));
@NotNull String options = PortalUtil.filterName(event.getLine(3)).toLowerCase(); @NotNull String options = PortalHandler.filterName(event.getLine(3)).toLowerCase();
PortalStrings portalStrings = new PortalStrings(portalName, network, destinationName); PortalStrings portalStrings = new PortalStrings(portalName, network, destinationName);
//Get portal options available to the player creating the portal //Get portal options available to the player creating the portal
Map<PortalOption, Boolean> portalOptions = PortalUtil.getPortalOptions(player, destinationName, options); Map<PortalOption, Boolean> portalOptions = PortalHandler.getPortalOptions(player, destinationName, options);
//Get the yaw //Get the yaw
float yaw = DirectionHelper.getYawFromLocationDifference(signControlBlock.getLocation(),
signLocation.getLocation());
//Get the direction the button should be facing
BlockFace buttonFacing = DirectionHelper.getBlockFaceFromYaw(yaw);
BlockFace facing = DirectionHelper.getFacing(signLocation); PortalLocation portalLocation = new PortalLocation();
if (facing == null) { portalLocation.setButtonFacing(buttonFacing).setYaw(yaw).setSignLocation(signLocation);
facing = DirectionHelper.getBlockFaceFromLocationDifference(signControlBlock.getLocation(),
signLocation.getLocation());
}
PortalLocation portalLocation = new PortalLocation(signLocation, facing);
Stargate.debug(route, "Finished getting all portal info"); Stargate.debug(route, "Finished getting all portal info");
return createPortal(portalStrings, portalOptions, portalLocation); return createPortal(portalStrings, portalOptions, yaw, portalLocation);
} }
@Nullable @Nullable
private Portal createPortal(@NotNull PortalStrings portalStrings, @NotNull Map<PortalOption, Boolean> portalOptions, private Portal createPortal(@NotNull PortalStrings portalStrings, @NotNull Map<PortalOption, Boolean> portalOptions,
@NotNull PortalLocation portalLocation) { float yaw, @NotNull PortalLocation portalLocation) {
String route = "PortalCreator::createPortal"; String route = "PortalCreator::createPortal";
//Try and find a gate matching the new portal //Try and find a gate matching the new portal
Gate gate = PortalUtil.findMatchingGate(portalLocation); Gate gate = PortalHandler.findMatchingGate(portalLocation, player.getWorld());
if ((gate == null) || (portalLocation.getButtonBlock() == null)) { if ((gate == null) || (portalLocation.getButtonVector() == null)) {
Stargate.debug(route, "Could not find matching gate layout"); Stargate.debug(route, "Could not find matching gate layout");
return null; return null;
} }
//If the portal is a bungee portal and invalid, abort here //If the portal is a bungee portal and invalid, abort here
if (!PortalUtil.isValidBungeePortal(portalOptions, player, portalStrings.destination(), if (!PortalHandler.isValidBungeePortal(portalOptions, player, portalStrings.destination(),
portalStrings.network())) { portalStrings.network())) {
Stargate.debug(route, "Portal is an invalid bungee portal"); Stargate.debug(route, "Portal is an invalid bungee portal");
return null; return null;
@@ -152,7 +151,7 @@ public class PortalCreator {
} }
//Check if a conflict exists //Check if a conflict exists
if (conflictsWithExistingPortal(gate, portalLocation, player)) { if (conflictsWithExistingPortal(gate, portalLocation.getTopLeft(), yaw, player)) {
return null; return null;
} }
@@ -210,9 +209,9 @@ public class PortalCreator {
//Check if the user can create portals to this world. //Check if the user can create portals to this world.
if (!bungee && !destinationName.isEmpty()) { if (!bungee && !destinationName.isEmpty()) {
Portal destinationPortal = PortalUtil.getByName(destinationName, network); Portal destinationPortal = PortalHandler.getByName(destinationName, network);
if (destinationPortal != null) { if (destinationPortal != null && destinationPortal.getWorld() != null) {
String world = destinationPortal.getLocation().getWorld().getName(); String world = destinationPortal.getWorld().getName();
if (PermissionHelper.cannotAccessWorld(player, world)) { if (PermissionHelper.cannotAccessWorld(player, world)) {
Stargate.debug("PortalCreator::canCreatePortal", "Player does not have access to destination world"); Stargate.debug("PortalCreator::canCreatePortal", "Player does not have access to destination world");
return new SGFormatBuilder(Message.CREATION_WORLD_DENIED).toString(); return new SGFormatBuilder(Message.CREATION_WORLD_DENIED).toString();
@@ -266,19 +265,21 @@ public class PortalCreator {
//Add button if the portal is not always on //Add button if the portal is not always on
if (!portalOptions.isAlwaysOn()) { if (!portalOptions.isAlwaysOn()) {
PortalFileHelper.generatePortalButton(portal, portalLocation.getFacing()); PortalFileHelper.generatePortalButton(portal, portalLocation.getButtonFacing());
} }
//Register the new portal //Register the new portal
PortalUtil.registerPortal(portal); PortalHandler.registerPortal(portal);
updateNewPortalOpenState(destinationName); updateNewPortalOpenState(destinationName);
//Update portals pointing at this one if it's not a bungee portal //Update portals pointing at this one if it's not a bungee portal
if (!portal.getOptions().isBungee()) { if (!portal.getOptions().isBungee()) {
PortalUtil.updatePortalsPointingAtNewPortal(portal); PortalHandler.updatePortalsPointingAtNewPortal(portal);
} }
PortalFileHelper.saveAllPortals(portal.getLocation().getWorld()); if (portal.getWorld() != null) {
PortalFileHelper.saveAllPortals(portal.getWorld());
}
return portal; return portal;
} }
@@ -310,14 +311,14 @@ public class PortalCreator {
} }
} else { } else {
//Check if the portal name has been duplicated on the network //Check if the portal name has been duplicated on the network
if (PortalUtil.getByName(portal.getCleanName(), portal.getCleanNetwork()) != null) { if (PortalHandler.getByName(portal.getCleanName(), portal.getCleanNetwork()) != null) {
Stargate.debug(route, "Gate name duplicate"); Stargate.debug(route, "Gate name duplicate");
new SGFormatBuilder(Message.CREATION_NAME_COLLISION).error(player); new SGFormatBuilder(Message.CREATION_NAME_COLLISION).error(player);
return false; return false;
} }
//Check if the number of portals in the network has been surpassed //Check if the number of portals in the network has been surpassed
List<String> networkList = PortalUtil.getNetwork(portal.getCleanNetwork()); List<String> networkList = PortalHandler.getNetwork(portal.getCleanNetwork());
int maxGates = Stargate.getGateConfig().maxGatesEachNetwork(); int maxGates = Stargate.getGateConfig().maxGatesEachNetwork();
if (maxGates > 0 && networkList != null && networkList.size() >= maxGates) { if (maxGates > 0 && networkList != null && networkList.size() >= maxGates) {
new SGFormatBuilder(Message.CREATION_NETWORK_FULL).error(player); new SGFormatBuilder(Message.CREATION_NETWORK_FULL).error(player);
@@ -350,7 +351,7 @@ public class PortalCreator {
portal.getPortalOpener().openPortal(true); portal.getPortalOpener().openPortal(true);
} else if (portal.getOptions().isAlwaysOn()) { } else if (portal.getOptions().isAlwaysOn()) {
//For a normal always-on portal, open both the portal and the destination //For a normal always-on portal, open both the portal and the destination
Portal destinationPortal = PortalUtil.getByName(destinationName, portal.getCleanNetwork()); Portal destinationPortal = PortalHandler.getByName(destinationName, portal.getCleanNetwork());
if (destinationPortal != null) { if (destinationPortal != null) {
portal.getPortalOpener().openPortal(true); portal.getPortalOpener().openPortal(true);
destinationPortal.drawSign(); destinationPortal.drawSign();
@@ -362,7 +363,7 @@ public class PortalCreator {
portal.getGate().getPortalClosedMaterials()).stream().toList(); portal.getGate().getPortalClosedMaterials()).stream().toList();
Material closedType = ListHelper.getRandom(possibleMaterials); Material closedType = ListHelper.getRandom(possibleMaterials);
for (Block entrance : portal.getStructure().getEntrances()) { for (BlockLocation entrance : portal.getStructure().getEntrances()) {
entrance.setType(closedType); entrance.setType(closedType);
} }
} }
@@ -371,16 +372,17 @@ public class PortalCreator {
/** /**
* Checks whether the new portal conflicts with an existing portal * Checks whether the new portal conflicts with an existing portal
* *
* @param gate <p>The gate type of the new portal</p> * @param gate <p>The gate type of the new portal</p>
* @param portalLocation <p>The location of the portal to check</p> * @param topLeft <p>The top-left block of the new portal</p>
* @param player <p>The player creating the new portal</p> * @param yaw <p>The yaw when looking directly outwards from the portal</p>
* @param player <p>The player creating the new portal</p>
* @return <p>True if a conflict was found. False otherwise</p> * @return <p>True if a conflict was found. False otherwise</p>
*/ */
private static boolean conflictsWithExistingPortal(@NotNull Gate gate, @NotNull PortalLocation portalLocation, private static boolean conflictsWithExistingPortal(@NotNull Gate gate, @NotNull BlockLocation topLeft, double yaw,
@NotNull Player player) { @NotNull Player player) {
for (BlockVector borderVector : gate.getLayout().getBorder()) { for (RelativeBlockVector borderVector : gate.getLayout().getBorder()) {
Block borderBlockLocation = portalLocation.getRelative(borderVector); BlockLocation borderBlockLocation = topLeft.getRelativeLocation(borderVector, yaw);
if (PortalUtil.getByBlock(borderBlockLocation) != null) { if (PortalHandler.getByBlock(borderBlockLocation.getBlock()) != null) {
Stargate.debug("PortalCreator::conflictsWithExistingPortal", Stargate.debug("PortalCreator::conflictsWithExistingPortal",
"Gate conflicts with existing gate"); "Gate conflicts with existing gate");
new SGFormatBuilder(Message.CREATION_CONFLICT).error(player); new SGFormatBuilder(Message.CREATION_CONFLICT).error(player);

View File

@@ -1,23 +1,24 @@
package net.knarcraft.stargate.utility; package net.knarcraft.stargate.portal;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.config.Permission; import net.knarcraft.stargate.config.Permission;
import net.knarcraft.stargate.config.formatting.Message; import net.knarcraft.stargate.config.formatting.Message;
import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.config.formatting.SGFormatBuilder;
import net.knarcraft.stargate.config.material.BukkitTagSpecifier; import net.knarcraft.stargate.config.material.BukkitTagSpecifier;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.container.BlockLocation;
import net.knarcraft.stargate.portal.PortalRegistry; import net.knarcraft.stargate.container.RelativeBlockVector;
import net.knarcraft.stargate.portal.property.PortalLocation; import net.knarcraft.stargate.portal.property.PortalLocation;
import net.knarcraft.stargate.portal.property.PortalOption; import net.knarcraft.stargate.portal.property.PortalOption;
import net.knarcraft.stargate.portal.property.PortalStructure; import net.knarcraft.stargate.portal.property.PortalStructure;
import net.knarcraft.stargate.portal.property.gate.Gate; import net.knarcraft.stargate.portal.property.gate.Gate;
import net.knarcraft.stargate.portal.property.gate.GateHandler; import net.knarcraft.stargate.portal.property.gate.GateHandler;
import net.knarcraft.stargate.utility.MaterialHelper;
import net.knarcraft.stargate.utility.PermissionHelper;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Tag; import org.bukkit.Tag;
import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -29,9 +30,9 @@ import java.util.Map;
/** /**
* Keeps track of all loaded portals, and handles portal creation * Keeps track of all loaded portals, and handles portal creation
*/ */
public final class PortalUtil { public class PortalHandler {
private PortalUtil() { private PortalHandler() {
} }
@@ -70,15 +71,18 @@ public final class PortalUtil {
List<String> destinations = new ArrayList<>(); List<String> destinations = new ArrayList<>();
List<String> portalsInNetwork = PortalRegistry.getNetwork(network); List<String> portalsInNetwork = PortalRegistry.getNetwork(network);
if (portalsInNetwork == null) { if (portalsInNetwork == null) {
Stargate.debug("PortalHandler::getDestinations", "Portal network " + network + " is null");
return List.of(); return List.of();
} }
for (String destination : portalsInNetwork) { for (String destination : portalsInNetwork) {
Portal portal = getByName(destination, network); Portal portal = getByName(destination, network);
if (portal == null) { if (portal == null) {
Stargate.debug("PortalHandler::getDestinations", "Invalid portal with name " + destination);
continue; continue;
} }
if (isDestinationAvailable(entrancePortal, portal, player)) { if (isDestinationAvailable(entrancePortal, portal, player)) {
Stargate.debug("PortalHandler::getDestinations", "Found available destination " + portal.getName());
destinations.add(portal.getName()); destinations.add(portal.getName());
} }
} }
@@ -117,7 +121,9 @@ public final class PortalUtil {
return true; return true;
} }
//Check if this player can access the destination world //Check if this player can access the destination world
if (PermissionHelper.cannotAccessWorld(player, destinationPortal.getLocation().getWorld().getName())) { if (destinationPortal.getWorld() != null && PermissionHelper.cannotAccessWorld(player,
destinationPortal.getWorld().getName())) {
Stargate.debug("PortalHandler::isDestinationAvailable", "Missing permission for destination world");
return false; return false;
} }
//The portal is visible to the player //The portal is visible to the player
@@ -164,33 +170,36 @@ public final class PortalUtil {
* Tries to find a gate matching the portal the user is trying to create * Tries to find a gate matching the portal the user is trying to create
* *
* @param portalLocation <p>The location data for the new portal</p> * @param portalLocation <p>The location data for the new portal</p>
* @param world <p>The world the player is located in</p>
* @return <p>The matching gate type, or null if no such gate could be found</p> * @return <p>The matching gate type, or null if no such gate could be found</p>
*/ */
@Nullable @Nullable
public static Gate findMatchingGate(@NotNull PortalLocation portalLocation) { public static Gate findMatchingGate(@NotNull PortalLocation portalLocation, @NotNull World world) {
Block signParent = DirectionHelper.getParent(portalLocation.getSignBlock()); Block signParent = portalLocation.getSignLocation().getParent();
if (signParent == null) { if (signParent == null) {
return null; return null;
} }
BlockLocation parent = new BlockLocation(world, signParent.getX(), signParent.getY(),
signParent.getZ());
//Get all gates with the used type of control blocks //Get all gates with the used type of control blocks
List<Gate> possibleGates = GateHandler.getGatesByControlBlock(signParent); List<Gate> possibleGates = GateHandler.getGatesByControlBlock(signParent);
double yaw = portalLocation.getYaw();
Gate gate = null; Gate gate = null;
for (Gate possibleGate : possibleGates) { for (Gate possibleGate : possibleGates) {
//Get gate controls //Get gate controls
BlockVector[] vectors = possibleGate.getLayout().getControls(); RelativeBlockVector[] vectors = possibleGate.getLayout().getControls();
portalLocation.setButtonBlock(null); portalLocation.setButtonVector(null);
for (BlockVector controlVector : vectors) { for (RelativeBlockVector controlVector : vectors) {
//Assuming the top-left location is pointing to the gate's top-left location, check if it's a match //Assuming the top-left location is pointing to the gate's top-left location, check if it's a match
Block possibleTopLocation = portalLocation.getRelative(controlVector); BlockLocation possibleTopLocation = parent.getRelativeLocation(controlVector.invert(), yaw);
if (possibleGate.matches(possibleTopLocation, portalLocation.getYaw(), true)) {
if (possibleGate.matches(possibleTopLocation, portalLocation.getFacing(), true)) {
gate = possibleGate; gate = possibleGate;
portalLocation.setTopLeft(possibleTopLocation); portalLocation.setTopLeft(possibleTopLocation);
} else { } else {
portalLocation.setButtonBlock(possibleTopLocation); portalLocation.setButtonVector(controlVector);
} }
} }
@@ -217,7 +226,7 @@ public final class PortalUtil {
Portal origin = getByName(originName, portal.getCleanNetwork()); Portal origin = getByName(originName, portal.getCleanNetwork());
if (origin == null || if (origin == null ||
!Portal.cleanString(origin.getDestinationName()).equals(portal.getCleanName()) || !Portal.cleanString(origin.getDestinationName()).equals(portal.getCleanName()) ||
!new BukkitTagSpecifier(Tag.WALL_SIGNS).asMaterials().contains(origin.getLocation().getSignBlock().getType())) { !new BukkitTagSpecifier(Tag.WALL_SIGNS).asMaterials().contains(origin.getLocation().getSignLocation().getType())) {
continue; continue;
} }
//Update sign of fixed gates pointing at this gate //Update sign of fixed gates pointing at this gate
@@ -295,7 +304,8 @@ public final class PortalUtil {
if (location.getWorld() == null) { if (location.getWorld() == null) {
return null; return null;
} }
return PortalRegistry.getPortalFromEntrance(location.getBlock()); return PortalRegistry.getPortalFromEntrance(new BlockLocation(location.getWorld(), location.getBlockX(),
location.getBlockY(), location.getBlockZ()));
} }
/** /**
@@ -306,7 +316,7 @@ public final class PortalUtil {
*/ */
@Nullable @Nullable
public static Portal getByEntrance(@NotNull Block block) { public static Portal getByEntrance(@NotNull Block block) {
return PortalRegistry.getPortalFromEntrance(block); return PortalRegistry.getPortalFromEntrance(new BlockLocation(block));
} }
/** /**
@@ -329,24 +339,24 @@ public final class PortalUtil {
*/ */
@Nullable @Nullable
public static Portal getByAdjacentEntrance(@NotNull Location location, int range) { public static Portal getByAdjacentEntrance(@NotNull Location location, int range) {
List<Block> adjacentPositions = new ArrayList<>(); List<BlockLocation> adjacentPositions = new ArrayList<>();
Block centerLocation = location.getBlock(); BlockLocation centerLocation = new BlockLocation(location.getBlock());
adjacentPositions.add(centerLocation); adjacentPositions.add(centerLocation);
for (int index = 1; index <= range; index++) { for (int index = 1; index <= range; index++) {
adjacentPositions.add(location.clone().add(new Vector(index, 0, 0)).getBlock()); adjacentPositions.add(centerLocation.makeRelativeBlockLocation(index, 0, 0));
adjacentPositions.add(location.clone().add(new Vector(-index, 0, 0)).getBlock()); adjacentPositions.add(centerLocation.makeRelativeBlockLocation(-index, 0, 0));
adjacentPositions.add(location.clone().add(new Vector(0, 0, index)).getBlock()); adjacentPositions.add(centerLocation.makeRelativeBlockLocation(0, 0, index));
adjacentPositions.add(location.clone().add(new Vector(0, 0, -index)).getBlock()); adjacentPositions.add(centerLocation.makeRelativeBlockLocation(0, 0, -index));
if (index < range) { if (index < range) {
adjacentPositions.add(location.clone().add(new Vector(index, 0, index)).getBlock()); adjacentPositions.add(centerLocation.makeRelativeBlockLocation(index, 0, index));
adjacentPositions.add(location.clone().add(new Vector(-index, 0, -index)).getBlock()); adjacentPositions.add(centerLocation.makeRelativeBlockLocation(-index, 0, -index));
adjacentPositions.add(location.clone().add(new Vector(index, 0, -index)).getBlock()); adjacentPositions.add(centerLocation.makeRelativeBlockLocation(index, 0, -index));
adjacentPositions.add(location.clone().add(new Vector(-index, 0, index)).getBlock()); adjacentPositions.add(centerLocation.makeRelativeBlockLocation(-index, 0, index));
} }
} }
for (Block adjacentPosition : adjacentPositions) { for (BlockLocation adjacentPosition : adjacentPositions) {
Portal portal = PortalRegistry.getPortalFromEntrance(adjacentPosition); Portal portal = PortalRegistry.getPortalFromEntrance(adjacentPosition);
if (portal != null) { if (portal != null) {
return portal; return portal;
@@ -363,7 +373,7 @@ public final class PortalUtil {
*/ */
@Nullable @Nullable
public static Portal getByControl(@NotNull Block block) { public static Portal getByControl(@NotNull Block block) {
return PortalRegistry.getPortalFromControl(block); return PortalRegistry.getPortalFromControl(new BlockLocation(block));
} }
/** /**
@@ -374,7 +384,7 @@ public final class PortalUtil {
*/ */
@Nullable @Nullable
public static Portal getByBlock(@NotNull Block block) { public static Portal getByBlock(@NotNull Block block) {
return PortalRegistry.getPortalFromFrame(block); return PortalRegistry.getPortalFromFrame(new BlockLocation(block));
} }
/** /**
@@ -435,12 +445,11 @@ public final class PortalUtil {
Stargate.debug("PortalHandler::verifyAllPortals", "Checking portal: " + portal.getName() + " | " + portal.getNetwork()); Stargate.debug("PortalHandler::verifyAllPortals", "Checking portal: " + portal.getName() + " | " + portal.getNetwork());
if (!portal.getOptions().hasNoSign() && !(new BukkitTagSpecifier(Tag.WALL_SIGNS).asMaterials().contains( if (!portal.getOptions().hasNoSign() && !(new BukkitTagSpecifier(Tag.WALL_SIGNS).asMaterials().contains(
portal.getLocation().getSignBlock().getType()))) { portal.getLocation().getSignLocation().getType()))) {
Stargate.debug("PortalHandler::verifyAllPortals", "Stargate is missing its sign"); Stargate.debug("PortalHandler::verifyAllPortals", "Stargate is missing its sign");
invalidPortals.add(portal); invalidPortals.add(portal);
} else if (!portal.getOptions().isAlwaysOn() && portal.getLocation().getButtonBlock() != null && } else if (!portal.getOptions().isAlwaysOn() && portal.getLocation().getButtonVector() != null &&
!MaterialHelper.isButtonCompatible(portal.getLocation().getButtonBlock().getLocation().add( !MaterialHelper.isButtonCompatible(portal.getBlockAt(portal.getLocation().getButtonVector().addOut(1)).getType())) {
new Vector(0, 0, 1)).getBlock().getType())) {
Stargate.debug("PortalHandler::verifyAllPortals", "Stargate is missing a valid button"); Stargate.debug("PortalHandler::verifyAllPortals", "Stargate is missing a valid button");
invalidPortals.add(portal); invalidPortals.add(portal);
} else if (!structure.checkIntegrity()) { } else if (!structure.checkIntegrity()) {
@@ -462,13 +471,14 @@ public final class PortalUtil {
*/ */
private static void unregisterInvalidPortal(@NotNull Portal portal) { private static void unregisterInvalidPortal(@NotNull Portal portal) {
//Show debug information //Show debug information
for (BlockVector control : portal.getGate().getLayout().getControls()) { for (RelativeBlockVector control : portal.getGate().getLayout().getControls()) {
Block block = portal.getLocation().getRelative(control); Block block = portal.getBlockAt(control).getBlock();
//Log control blocks not matching the gate layout //Log control blocks not matching the gate layout
if (!MaterialHelper.specifiersToMaterials(portal.getGate().getControlBlockMaterials()).contains( if (!MaterialHelper.specifiersToMaterials(portal.getGate().getControlBlockMaterials()).contains(
block.getType())) { block.getType())) {
Stargate.debug("PortalHandler::unregisterInvalidPortal", "Control Block Type == " + Stargate.debug("PortalHandler::unregisterInvalidPortal", "Control Block Type == " +
block.getType().name()); block.getType().name() + " at " + control + " real: " + block + " facing " +
portal.getLocation().getYaw());
} }
} }
PortalRegistry.unregisterPortal(portal, false); PortalRegistry.unregisterPortal(portal, false);

View File

@@ -3,6 +3,7 @@ package net.knarcraft.stargate.portal;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.config.material.BukkitTagSpecifier; import net.knarcraft.stargate.config.material.BukkitTagSpecifier;
import net.knarcraft.stargate.container.BlockChangeRequest; import net.knarcraft.stargate.container.BlockChangeRequest;
import net.knarcraft.stargate.container.BlockLocation;
import net.knarcraft.stargate.event.StargateCloseEvent; import net.knarcraft.stargate.event.StargateCloseEvent;
import net.knarcraft.stargate.event.StargateOpenEvent; import net.knarcraft.stargate.event.StargateOpenEvent;
import net.knarcraft.stargate.portal.property.PortalOptions; import net.knarcraft.stargate.portal.property.PortalOptions;
@@ -11,7 +12,6 @@ import net.knarcraft.stargate.utility.MaterialHelper;
import org.bukkit.Axis; import org.bukkit.Axis;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Tag; import org.bukkit.Tag;
import org.bukkit.block.Block;
import org.bukkit.block.data.Orientable; import org.bukkit.block.data.Orientable;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -98,10 +98,10 @@ public class PortalOpener {
Material openType = ListHelper.getRandom(possibleMaterials); Material openType = ListHelper.getRandom(possibleMaterials);
//Adjust orientation if applicable //Adjust orientation if applicable
Axis axis = (openType.createBlockData() instanceof Orientable) ? portal.getLocation().getVectorOperation().getNormalAxis() : null; Axis axis = (openType.createBlockData() instanceof Orientable) ? portal.getLocation().getRotationAxis() : null;
//Change the entrance blocks to the correct type //Change the entrance blocks to the correct type
for (Block inside : portal.getStructure().getEntrances()) { for (BlockLocation inside : portal.getStructure().getEntrances()) {
Stargate.addControlBlockUpdateRequest(new BlockChangeRequest(inside, openType, axis)); Stargate.addControlBlockUpdateRequest(new BlockChangeRequest(inside, openType, axis));
} }
@@ -147,7 +147,7 @@ public class PortalOpener {
destination.getPortalActivator().setDestination(portal); destination.getPortalActivator().setDestination(portal);
//Update the destination's sign if it exists //Update the destination's sign if it exists
if (new BukkitTagSpecifier(Tag.WALL_SIGNS).asMaterials().contains(destination.getLocation().getSignBlock().getType())) { if (new BukkitTagSpecifier(Tag.WALL_SIGNS).asMaterials().contains(destination.getLocation().getSignLocation().getType())) {
destination.drawSign(); destination.drawSign();
} }
} }
@@ -182,9 +182,9 @@ public class PortalOpener {
Material closedType = ListHelper.getRandom(possibleMaterials); Material closedType = ListHelper.getRandom(possibleMaterials);
//Adjust orientation if applicable //Adjust orientation if applicable
Axis axis = (closedType.createBlockData() instanceof Orientable) ? portal.getLocation().getVectorOperation().getNormalAxis() : null; Axis axis = (closedType.createBlockData() instanceof Orientable) ? portal.getLocation().getRotationAxis() : null;
for (Block entrance : portal.getStructure().getEntrances()) { for (BlockLocation entrance : portal.getStructure().getEntrances()) {
Stargate.addControlBlockUpdateRequest(new BlockChangeRequest(entrance, closedType, axis)); Stargate.addControlBlockUpdateRequest(new BlockChangeRequest(entrance, closedType, axis));
} }

View File

@@ -3,11 +3,10 @@ package net.knarcraft.stargate.portal;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.config.addons.DynmapManager; import net.knarcraft.stargate.config.addons.DynmapManager;
import net.knarcraft.stargate.config.material.BukkitTagSpecifier; import net.knarcraft.stargate.config.material.BukkitTagSpecifier;
import net.knarcraft.stargate.container.BlockLocation;
import net.knarcraft.stargate.utility.PortalFileHelper; import net.knarcraft.stargate.utility.PortalFileHelper;
import net.knarcraft.stargate.utility.PortalUtil;
import org.bukkit.Tag; import org.bukkit.Tag;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -21,9 +20,9 @@ import java.util.Map;
*/ */
public class PortalRegistry { public class PortalRegistry {
private static final Map<Block, Portal> lookupBlocks = new HashMap<>(); private static final Map<BlockLocation, Portal> lookupBlocks = new HashMap<>();
private static final Map<Block, Portal> lookupEntrances = new HashMap<>(); private static final Map<BlockLocation, Portal> lookupEntrances = new HashMap<>();
private static final Map<Block, Portal> lookupControls = new HashMap<>(); private static final Map<BlockLocation, Portal> lookupControls = new HashMap<>();
private static final Map<String, Map<String, Portal>> portalLookupByNetwork = new HashMap<>(); private static final Map<String, Map<String, Portal>> portalLookupByNetwork = new HashMap<>();
private static final Map<String, List<String>> allPortalNetworks = new HashMap<>(); private static final Map<String, List<String>> allPortalNetworks = new HashMap<>();
@@ -53,7 +52,7 @@ public class PortalRegistry {
//Storing the portals to clear is necessary to avoid a concurrent modification exception //Storing the portals to clear is necessary to avoid a concurrent modification exception
List<Portal> portalsToRemove = new ArrayList<>(); List<Portal> portalsToRemove = new ArrayList<>();
allPortals.forEach((portal) -> { allPortals.forEach((portal) -> {
if (portal.getLocation().getWorld().equals(world)) { if (portal.getWorld() != null && portal.getWorld().equals(world)) {
portalsToRemove.add(portal); portalsToRemove.add(portal);
} }
}); });
@@ -104,7 +103,7 @@ public class PortalRegistry {
* @return <p>The portal the frame block belongs to, or null</p> * @return <p>The portal the frame block belongs to, or null</p>
*/ */
@Nullable @Nullable
public static Portal getPortalFromFrame(@NotNull Block blockLocation) { public static Portal getPortalFromFrame(@NotNull BlockLocation blockLocation) {
return lookupBlocks.get(blockLocation); return lookupBlocks.get(blockLocation);
} }
@@ -115,7 +114,7 @@ public class PortalRegistry {
* @return <p>The portal the control block belongs to, or null</p> * @return <p>The portal the control block belongs to, or null</p>
*/ */
@Nullable @Nullable
public static Portal getPortalFromControl(@NotNull Block blockLocation) { public static Portal getPortalFromControl(@NotNull BlockLocation blockLocation) {
return lookupControls.get(blockLocation); return lookupControls.get(blockLocation);
} }
@@ -142,7 +141,7 @@ public class PortalRegistry {
* @return <p>A portal, or null</p> * @return <p>A portal, or null</p>
*/ */
@Nullable @Nullable
public static Portal getPortalFromEntrance(@NotNull Block blockLocation) { public static Portal getPortalFromEntrance(@NotNull BlockLocation blockLocation) {
return lookupEntrances.get(blockLocation); return lookupEntrances.get(blockLocation);
} }
@@ -204,9 +203,9 @@ public class PortalRegistry {
//Update all portals in the same network with this portal as its destination //Update all portals in the same network with this portal as its destination
for (String originName : allPortalNetworks.get(networkName)) { for (String originName : allPortalNetworks.get(networkName)) {
Portal origin = PortalUtil.getByName(originName, portal.getCleanNetwork()); Portal origin = PortalHandler.getByName(originName, portal.getCleanNetwork());
if (origin == null || !origin.getDestinationName().equalsIgnoreCase(portalName) || if (origin == null || !origin.getDestinationName().equalsIgnoreCase(portalName) ||
!new BukkitTagSpecifier(Tag.WALL_SIGNS).asMaterials().contains(origin.getLocation().getSignBlock().getType())) { !new BukkitTagSpecifier(Tag.WALL_SIGNS).asMaterials().contains(origin.getLocation().getSignLocation().getType())) {
continue; continue;
} }
//Update the portal's sign //Update the portal's sign
@@ -223,7 +222,9 @@ public class PortalRegistry {
//Mark the portal's sign as unregistered //Mark the portal's sign as unregistered
new PortalSignDrawer(portal).drawUnregisteredSign(); new PortalSignDrawer(portal).drawUnregisteredSign();
PortalFileHelper.saveAllPortals(portal.getLocation().getWorld()); if (portal.getWorld() != null) {
PortalFileHelper.saveAllPortals(portal.getWorld());
}
portal.setRegistered(false); portal.setRegistered(false);
DynmapManager.removePortalMarker(portal); DynmapManager.removePortalMarker(portal);
} }
@@ -236,22 +237,22 @@ public class PortalRegistry {
*/ */
private static void clearLookupMaps(@NotNull Portal portal, boolean removeAll) { private static void clearLookupMaps(@NotNull Portal portal, boolean removeAll) {
//Remove portal from lookup blocks //Remove portal from lookup blocks
for (Block block : portal.getStructure().getFrame()) { for (BlockLocation block : portal.getStructure().getFrame()) {
lookupBlocks.remove(block); lookupBlocks.remove(block);
} }
//Remove registered info about the lookup controls and blocks //Remove registered info about the lookup controls and blocks
lookupBlocks.remove(portal.getLocation().getSignBlock()); lookupBlocks.remove(portal.getSignLocation());
lookupControls.remove(portal.getLocation().getSignBlock()); lookupControls.remove(portal.getSignLocation());
Block button = portal.getStructure().getButton(); BlockLocation button = portal.getStructure().getButton();
if (button != null) { if (button != null) {
lookupBlocks.remove(button); lookupBlocks.remove(button);
lookupControls.remove(button); lookupControls.remove(button);
} }
//Remove entrances //Remove entrances
for (Block entrance : portal.getStructure().getEntrances()) { for (BlockLocation entrance : portal.getStructure().getEntrances()) {
lookupEntrances.remove(entrance); lookupEntrances.remove(entrance);
} }
@@ -302,23 +303,23 @@ public class PortalRegistry {
} }
//Register all frame blocks to the lookup list //Register all frame blocks to the lookup list
for (Block block : portal.getStructure().getFrame()) { for (BlockLocation block : portal.getStructure().getFrame()) {
lookupBlocks.put(block, portal); lookupBlocks.put(block, portal);
} }
//Register the sign and button to the lookup lists //Register the sign and button to the lookup lists
if (!portal.getOptions().hasNoSign()) { if (!portal.getOptions().hasNoSign()) {
lookupBlocks.put(portal.getLocation().getSignBlock(), portal); lookupBlocks.put(portal.getSignLocation(), portal);
lookupControls.put(portal.getLocation().getSignBlock(), portal); lookupControls.put(portal.getSignLocation(), portal);
} }
Block button = portal.getStructure().getButton(); BlockLocation button = portal.getStructure().getButton();
if (button != null) { if (button != null) {
lookupBlocks.put(button, portal); lookupBlocks.put(button, portal);
lookupControls.put(button, portal); lookupControls.put(button, portal);
} }
//Register entrances to the lookup list //Register entrances to the lookup list
for (Block entrance : portal.getStructure().getEntrances()) { for (BlockLocation entrance : portal.getStructure().getEntrances()) {
lookupEntrances.put(entrance, portal); lookupEntrances.put(entrance, portal);
} }

View File

@@ -8,7 +8,6 @@ import net.knarcraft.stargate.config.formatting.SGFormatBuilder;
import net.knarcraft.stargate.container.SignData; import net.knarcraft.stargate.container.SignData;
import net.knarcraft.stargate.portal.property.PortalLocation; import net.knarcraft.stargate.portal.property.PortalLocation;
import net.knarcraft.stargate.utility.PermissionHelper; import net.knarcraft.stargate.utility.PermissionHelper;
import net.knarcraft.stargate.utility.PortalUtil;
import net.knarcraft.stargate.utility.SignHelper; import net.knarcraft.stargate.utility.SignHelper;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
@@ -131,7 +130,7 @@ public class PortalSignDrawer {
*/ */
@Nullable @Nullable
private Sign getSign() { private Sign getSign() {
Block signBlock = portal.getLocation().getSignBlock(); Block signBlock = portal.getSignLocation().getBlock();
BlockState state = signBlock.getState(); BlockState state = signBlock.getState();
if (!(state instanceof Sign sign)) { if (!(state instanceof Sign sign)) {
if (!portal.getOptions().hasNoSign()) { if (!portal.getOptions().hasNoSign()) {
@@ -273,7 +272,7 @@ public class PortalSignDrawer {
ChatColor highlightColor = signData.getHighlightSignColor(); ChatColor highlightColor = signData.getHighlightSignColor();
ChatColor mainColor = signData.getMainSignColor(); ChatColor mainColor = signData.getMainSignColor();
if (freeGatesColored) { if (freeGatesColored) {
Portal destination = PortalUtil.getByName(portal.getDestinationName(), portal.getNetwork()); Portal destination = PortalHandler.getByName(portal.getDestinationName(), portal.getNetwork());
boolean free = PermissionHelper.isFree(Objects.requireNonNull(portal.getActivePlayer()), portal, destination); boolean free = PermissionHelper.isFree(Objects.requireNonNull(portal.getActivePlayer()), portal, destination);
ChatColor nameColor = (free ? freeColor : highlightColor); ChatColor nameColor = (free ? freeColor : highlightColor);
setLine(signData, signLineIndex, nameColor + ">" + (free ? freeColor : mainColor) + setLine(signData, signLineIndex, nameColor + ">" + (free ? freeColor : mainColor) +
@@ -312,7 +311,7 @@ public class PortalSignDrawer {
PortalActivator destinations = portal.getPortalActivator(); PortalActivator destinations = portal.getPortalActivator();
String destinationName = destinations.getDestinations().get(destinationIndex); String destinationName = destinations.getDestinations().get(destinationIndex);
if (freeGatesColored) { if (freeGatesColored) {
Portal destination = PortalUtil.getByName(destinationName, portal.getNetwork()); Portal destination = PortalHandler.getByName(destinationName, portal.getNetwork());
boolean free = PermissionHelper.isFree(Objects.requireNonNull(portal.getActivePlayer()), portal, destination); boolean free = PermissionHelper.isFree(Objects.requireNonNull(portal.getActivePlayer()), portal, destination);
setLine(signData, signLineIndex, (free ? freeColor : mainColor) + translateAllColorCodes(destinationName), output); setLine(signData, signLineIndex, (free ? freeColor : mainColor) + translateAllColorCodes(destinationName), output);
} else { } else {
@@ -366,7 +365,7 @@ public class PortalSignDrawer {
private void drawFixedSign(@NotNull SignData signData, @NotNull String[] output) { private void drawFixedSign(@NotNull SignData signData, @NotNull String[] output) {
ChatColor highlightColor = signData.getHighlightSignColor(); ChatColor highlightColor = signData.getHighlightSignColor();
ChatColor mainColor = signData.getMainSignColor(); ChatColor mainColor = signData.getMainSignColor();
Portal destinationPortal = PortalUtil.getByName(portal.getDestinationName(), portal.getCleanNetwork()); Portal destinationPortal = PortalHandler.getByName(portal.getDestinationName(), portal.getCleanNetwork());
String destinationName = portal.getOptions().isRandom() ? new SGFormatBuilder(Message.SIGN_RANDOM).toString() : String destinationName = portal.getOptions().isRandom() ? new SGFormatBuilder(Message.SIGN_RANDOM).toString() :
(destinationPortal != null ? destinationPortal.getName() : portal.getDestinationName()); (destinationPortal != null ? destinationPortal.getName() : portal.getDestinationName());
setLine(signData, 1, highlightColor + ">" + mainColor + translateAllColorCodes(destinationName) + setLine(signData, 1, highlightColor + ">" + mainColor + translateAllColorCodes(destinationName) +
@@ -378,7 +377,7 @@ public class PortalSignDrawer {
setLine(signData, 2, highlightColor + "(" + mainColor + setLine(signData, 2, highlightColor + "(" + mainColor +
translateAllColorCodes(portal.getNetwork()) + highlightColor + ")", output); translateAllColorCodes(portal.getNetwork()) + highlightColor + ")", output);
} }
Portal destination = PortalUtil.getByName(portal.getDestinationName(), portal.getNetwork()); Portal destination = PortalHandler.getByName(portal.getDestinationName(), portal.getNetwork());
if (destination == null && !portal.getOptions().isRandom()) { if (destination == null && !portal.getOptions().isRandom()) {
setLine(signData, 3, errorColor + new SGFormatBuilder(Message.SIGN_DISCONNECTED).toString(), output); setLine(signData, 3, errorColor + new SGFormatBuilder(Message.SIGN_DISCONNECTED).toString(), output);
} else { } else {
@@ -395,7 +394,7 @@ public class PortalSignDrawer {
*/ */
public static void markPortalWithInvalidGate(@NotNull PortalLocation portalLocation, @NotNull String gateName, public static void markPortalWithInvalidGate(@NotNull PortalLocation portalLocation, @NotNull String gateName,
int lineIndex) { int lineIndex) {
BlockState blockState = portalLocation.getSignBlock().getState(); BlockState blockState = portalLocation.getSignLocation().getBlock().getState();
if (!(blockState instanceof Sign sign)) { if (!(blockState instanceof Sign sign)) {
return; return;
} }

View File

@@ -1,10 +1,10 @@
package net.knarcraft.stargate.portal.property; package net.knarcraft.stargate.portal.property;
import net.knarcraft.stargate.transformation.SimpleVectorOperation; import net.knarcraft.stargate.container.BlockLocation;
import net.knarcraft.stargate.container.RelativeBlockVector;
import org.bukkit.Axis;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.util.BlockVector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -14,61 +14,29 @@ import org.jetbrains.annotations.Nullable;
@SuppressWarnings("UnusedReturnValue") @SuppressWarnings("UnusedReturnValue")
public class PortalLocation { public class PortalLocation {
private @Nullable Block topLeft; private BlockLocation topLeft;
private @NotNull BlockFace facing; private float yaw;
private @NotNull Block signBlock; private BlockLocation signLocation;
private @Nullable Block buttonBlock; private RelativeBlockVector buttonVector;
private final @NotNull World world; private BlockFace buttonFacing;
private final SimpleVectorOperation vectorOperation;
/**
* Instantiates a new portal location
*
* @param topLeft <p>The top-left block of the portal</p>
* @param facing <p>The direction the portal is facing</p>
* @param signBlock <p>The block the sign is attached to</p>
* @param buttonBlock <p>The block of the portal, or null if the portal doesn't need a button</p>
*/
public PortalLocation(@NotNull Block topLeft, @NotNull BlockFace facing, @NotNull Block signBlock,
@Nullable Block buttonBlock) {
this.world = topLeft.getWorld();
this.topLeft = topLeft;
this.facing = facing;
this.signBlock = signBlock;
this.buttonBlock = buttonBlock;
this.vectorOperation = new SimpleVectorOperation(facing);
}
/**
* Instantiates a new portal location
*
* @param signBlock <p>The block the sign is attached to</p>
* @param facing <p>The direction the portal is facing</p>
*/
public PortalLocation(@NotNull Block signBlock, @NotNull BlockFace facing) {
this.world = signBlock.getWorld();
this.signBlock = signBlock;
this.facing = facing;
this.vectorOperation = new SimpleVectorOperation(facing);
}
/** /**
* Gets the top-left block of the portal * Gets the top-left block of the portal
* *
* @return <p>The top-left block of the portal</p> * @return <p>The top-left block of the portal</p>
*/ */
@Nullable @NotNull
public Block getTopLeft() { public BlockLocation getTopLeft() {
return topLeft; return topLeft;
} }
/** /**
* Gets the block face the portal is facing towards * Gets the yaw for looking outwards from the portal
* *
* @return <p>The portal's facing direction</p> * @return <p>The portal's yaw</p>
*/ */
public BlockFace getFacing() { public float getYaw() {
return facing; return yaw;
} }
/** /**
@@ -77,8 +45,8 @@ public class PortalLocation {
* @return <p>The location of the portal's sign</p> * @return <p>The location of the portal's sign</p>
*/ */
@NotNull @NotNull
public Block getSignBlock() { public BlockLocation getSignLocation() {
return signBlock; return signLocation;
} }
/** /**
@@ -87,8 +55,30 @@ public class PortalLocation {
* @return <p>The relative location of the portal's button</p> * @return <p>The relative location of the portal's button</p>
*/ */
@Nullable @Nullable
public Block getButtonBlock() { public RelativeBlockVector getButtonVector() {
return buttonBlock; return buttonVector;
}
/**
* Gets the block face determining the button's direction
*
* @return <p>The button's block face</p>
*/
@NotNull
public BlockFace getButtonFacing() {
return buttonFacing;
}
/**
* Gets the rotation axis, which is the axis along which the gate is placed
*
* <p>The portal's rotation axis is the cross axis of the button's axis</p>
*
* @return <p>The portal's rotation axis</p>
*/
@NotNull
public Axis getRotationAxis() {
return getYaw() == 0.0F || getYaw() == 180.0F ? Axis.X : Axis.Z;
} }
/** /**
@@ -96,19 +86,9 @@ public class PortalLocation {
* *
* @return <p>The world this portal resides in</p> * @return <p>The world this portal resides in</p>
*/ */
@NotNull @Nullable
public World getWorld() { public World getWorld() {
return this.world; return topLeft.getWorld();
}
/**
* Gets the vector operation to use in order to convert this portal's relative vectors to the real space
*
* @return <p>The vector operation</p>
*/
@NotNull
public SimpleVectorOperation getVectorOperation() {
return this.vectorOperation;
} }
/** /**
@@ -121,62 +101,59 @@ public class PortalLocation {
* @return <p>The portal location Object</p> * @return <p>The portal location Object</p>
*/ */
@NotNull @NotNull
public PortalLocation setTopLeft(@NotNull Block topLeft) { public PortalLocation setTopLeft(@NotNull BlockLocation topLeft) {
this.topLeft = topLeft; this.topLeft = topLeft;
return this; return this;
} }
/** /**
* Sets the portal's facing direction * Sets the portal's yaw
* *
* <p>The portal's facing direction is the direction a player would get when looking directly out from the portal</p> * <p>The portal's yaw is the yaw a player would get when looking directly out from the portal</p>
* *
* @param facing <p>The portal's new facing direction</p> * @param yaw <p>The portal's new yaw</p>
* @return <p>The portal location Object</p> * @return <p>The portal location Object</p>
*/ */
@NotNull @NotNull
public PortalLocation setFacing(@NotNull BlockFace facing) { public PortalLocation setYaw(float yaw) {
this.facing = facing; this.yaw = yaw;
return this; return this;
} }
/** /**
* Sets the location of the portal's sign * Sets the location of the portal's sign
* *
* @param signBlock <p>The new sign location</p> * @param signLocation <p>The new sign location</p>
* @return <p>The portal location Object</p> * @return <p>The portal location Object</p>
*/ */
@NotNull @NotNull
public PortalLocation setSignBlock(@NotNull Block signBlock) { public PortalLocation setSignLocation(@NotNull BlockLocation signLocation) {
this.signBlock = signBlock; this.signLocation = signLocation;
return this; return this;
} }
/** /**
* Sets the relative location of the portal's button * Sets the relative location of the portal's button
* *
* @param buttonBlock <p>The new relative button location</p> * @param buttonVector <p>The new relative button location</p>
* @return <p>The portal location Object</p> * @return <p>The portal location Object</p>
*/ */
@NotNull @NotNull
public PortalLocation setButtonBlock(@Nullable Block buttonBlock) { public PortalLocation setButtonVector(@Nullable RelativeBlockVector buttonVector) {
this.buttonBlock = buttonBlock; this.buttonVector = buttonVector;
return this; return this;
} }
/** /**
* Gets a block relative to this portal's top-left block * Sets the block face for the direction the portal button is facing
* *
* @param vector <p>The relative vector pointing at the block</p> * @param buttonFacing <p>The new block face of the portal's button</p>
* @return <p>The block</p> * @return <p>The portal location Object</p>
* @throws IllegalStateException <p>If the top-left location is not set</p>
*/ */
@NotNull @NotNull
public Block getRelative(@NotNull BlockVector vector) throws IllegalStateException { public PortalLocation setButtonFacing(@NotNull BlockFace buttonFacing) {
if (this.topLeft == null) { this.buttonFacing = buttonFacing;
throw new IllegalStateException("Top-left is not set"); return this;
}
return this.vectorOperation.getRealLocationBlock(this.topLeft, vector);
} }
} }

View File

@@ -194,14 +194,4 @@ public class PortalOptions {
return this.options.get(PortalOption.INVISIBLE); return this.options.get(PortalOption.INVISIBLE);
} }
/**
* Checks whether the given portal option is true
*
* @param option <p>The option to check</p>
* @return <p>True if enabled for the portal</p>
*/
public boolean checkOption(@NotNull PortalOption option) {
return this.options.get(option);
}
} }

View File

@@ -1,10 +1,10 @@
package net.knarcraft.stargate.portal.property; package net.knarcraft.stargate.portal.property;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.container.BlockLocation;
import net.knarcraft.stargate.container.RelativeBlockVector;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.portal.property.gate.Gate; import net.knarcraft.stargate.portal.property.gate.Gate;
import org.bukkit.block.Block;
import org.bukkit.util.BlockVector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -18,9 +18,9 @@ public class PortalStructure {
private final Portal portal; private final Portal portal;
private final Gate gate; private final Gate gate;
private Block button; private BlockLocation button;
private Block[] frame; private BlockLocation[] frame;
private Block[] entrances; private BlockLocation[] entrances;
/** /**
* Instantiates a new portal structure * Instantiates a new portal structure
@@ -29,7 +29,7 @@ public class PortalStructure {
* @param gate <p>The gate type used by this portal structure</p> * @param gate <p>The gate type used by this portal structure</p>
* @param button <p>The real location of the portal's button</p> * @param button <p>The real location of the portal's button</p>
*/ */
public PortalStructure(@NotNull Portal portal, @NotNull Gate gate, @Nullable Block button) { public PortalStructure(@NotNull Portal portal, @NotNull Gate gate, @Nullable BlockLocation button) {
this.portal = portal; this.portal = portal;
this.gate = gate; this.gate = gate;
this.button = button; this.button = button;
@@ -51,7 +51,7 @@ public class PortalStructure {
* @return <p>The location of this portal's button</p> * @return <p>The location of this portal's button</p>
*/ */
@Nullable @Nullable
public Block getButton() { public BlockLocation getButton() {
return button; return button;
} }
@@ -60,7 +60,7 @@ public class PortalStructure {
* *
* @param button <p>The location of this portal's button</p> * @param button <p>The location of this portal's button</p>
*/ */
public void setButton(@NotNull Block button) { public void setButton(@NotNull BlockLocation button) {
this.button = button; this.button = button;
} }
@@ -71,7 +71,7 @@ public class PortalStructure {
*/ */
public boolean checkIntegrity() { public boolean checkIntegrity() {
if (Stargate.getGateConfig().verifyPortals()) { if (Stargate.getGateConfig().verifyPortals()) {
return gate.matches(portal.getLocation().getTopLeft(), portal.getLocation().getFacing()); return gate.matches(portal.getTopLeft(), portal.getYaw());
} else { } else {
return true; return true;
} }
@@ -87,10 +87,10 @@ public class PortalStructure {
* @return <p>A list of block locations</p> * @return <p>A list of block locations</p>
*/ */
@NotNull @NotNull
private Block[] relativeBlockVectorsToBlockLocations(@NotNull BlockVector[] vectors) { private BlockLocation[] relativeBlockVectorsToBlockLocations(@NotNull RelativeBlockVector[] vectors) {
Block[] locations = new Block[vectors.length]; BlockLocation[] locations = new BlockLocation[vectors.length];
for (int i = 0; i < vectors.length; i++) { for (int i = 0; i < vectors.length; i++) {
locations[i] = portal.getLocation().getRelative(vectors[i]); locations[i] = portal.getBlockAt(vectors[i]);
} }
return locations; return locations;
} }
@@ -101,7 +101,7 @@ public class PortalStructure {
* @return <p>The locations of this portal's entrances</p> * @return <p>The locations of this portal's entrances</p>
*/ */
@NotNull @NotNull
public Block[] getEntrances() { public BlockLocation[] getEntrances() {
if (entrances == null) { if (entrances == null) {
//Get the locations of the entrances once, and only if necessary as it's an expensive operation //Get the locations of the entrances once, and only if necessary as it's an expensive operation
entrances = relativeBlockVectorsToBlockLocations(gate.getLayout().getEntrances()); entrances = relativeBlockVectorsToBlockLocations(gate.getLayout().getEntrances());
@@ -115,7 +115,7 @@ public class PortalStructure {
* @return <p>The locations of this portal's frame</p> * @return <p>The locations of this portal's frame</p>
*/ */
@NotNull @NotNull
public Block[] getFrame() { public BlockLocation[] getFrame() {
if (frame == null) { if (frame == null) {
//Get the locations of the frame blocks once, and only if necessary as it's an expensive operation //Get the locations of the frame blocks once, and only if necessary as it's an expensive operation
frame = relativeBlockVectorsToBlockLocations(gate.getLayout().getBorder()); frame = relativeBlockVectorsToBlockLocations(gate.getLayout().getBorder());

View File

@@ -3,12 +3,10 @@ package net.knarcraft.stargate.portal.property.gate;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.config.material.BukkitMaterialSpecifier; import net.knarcraft.stargate.config.material.BukkitMaterialSpecifier;
import net.knarcraft.stargate.config.material.MaterialSpecifier; import net.knarcraft.stargate.config.material.MaterialSpecifier;
import net.knarcraft.stargate.transformation.SimpleVectorOperation; import net.knarcraft.stargate.container.BlockLocation;
import net.knarcraft.stargate.container.RelativeBlockVector;
import net.knarcraft.stargate.utility.MaterialHelper; import net.knarcraft.stargate.utility.MaterialHelper;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.util.BlockVector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -183,11 +181,11 @@ public class Gate {
* Checks whether a portal's gate matches this gate type * Checks whether a portal's gate matches this gate type
* *
* @param topLeft <p>The top-left block of the portal's gate</p> * @param topLeft <p>The top-left block of the portal's gate</p>
* @param facing <p>The direction the portal is facing</p> * @param yaw <p>The yaw when looking directly outwards</p>
* @return <p>True if this gate matches the portal</p> * @return <p>True if this gate matches the portal</p>
*/ */
public boolean matches(@NotNull Block topLeft, @NotNull BlockFace facing) { public boolean matches(@NotNull BlockLocation topLeft, double yaw) {
return matches(topLeft, facing, false); return matches(topLeft, yaw, false);
} }
/** /**
@@ -198,34 +196,34 @@ public class Gate {
* containing AIR or WATER will cause the gate to not match.</p> * containing AIR or WATER will cause the gate to not match.</p>
* *
* @param topLeft <p>The top-left block of the portal's gate</p> * @param topLeft <p>The top-left block of the portal's gate</p>
* @param facing <p>The direction the portal is facing</p> * @param yaw <p>The yaw when looking directly outwards</p>
* @param onCreate <p>Whether this is used in the context of creating a new gate</p> * @param onCreate <p>Whether this is used in the context of creating a new gate</p>
* @return <p>True if this gate matches the portal</p> * @return <p>True if this gate matches the portal</p>
*/ */
public boolean matches(@NotNull Block topLeft, @NotNull BlockFace facing, boolean onCreate) { public boolean matches(@NotNull BlockLocation topLeft, double yaw, boolean onCreate) {
return verifyGateEntrancesMatch(topLeft, facing, onCreate) && verifyGateBorderMatches(topLeft, facing); return verifyGateEntrancesMatch(topLeft, yaw, onCreate) && verifyGateBorderMatches(topLeft, yaw);
} }
/** /**
* Verifies that all border blocks of a portal matches this gate type * Verifies that all border blocks of a portal matches this gate type
* *
* @param topLeft <p>The top-left block of the portal's gate</p> * @param topLeft <p>The top-left block of the portal</p>
* @param facing <p>The direction the portal is facing</p> * @param yaw <p>The yaw when looking directly outwards from the portal</p>
* @return <p>True if all border blocks of the gate match the layout</p> * @return <p>True if all border blocks of the gate match the layout</p>
*/ */
private boolean verifyGateBorderMatches(@NotNull Block topLeft, @NotNull BlockFace facing) { private boolean verifyGateBorderMatches(@NotNull BlockLocation topLeft, double yaw) {
for (BlockVector borderVector : layout.getBorder()) { for (RelativeBlockVector borderVector : layout.getBorder()) {
int rowIndex = borderVector.getBlockX(); int rowIndex = borderVector.right();
int lineIndex = borderVector.getBlockY(); int lineIndex = borderVector.down();
Character key = layout.getLayout()[lineIndex][rowIndex]; Character key = layout.getLayout()[lineIndex][rowIndex];
List<MaterialSpecifier> materialInLayout = characterMaterialMap.get(key); List<MaterialSpecifier> materialInLayout = characterMaterialMap.get(key);
Material type = new SimpleVectorOperation(facing).getRealLocationBlock(topLeft, borderVector).getType(); Material materialAtLocation = topLeft.getRelativeLocation(borderVector, yaw).getType();
if (materialInLayout != null) { if (materialInLayout != null) {
if (!MaterialHelper.specifiersToMaterials(materialInLayout).contains(type)) { if (!MaterialHelper.specifiersToMaterials(materialInLayout).contains(materialAtLocation)) {
Stargate.debug("Gate::Matches", String.format("Block Type Mismatch: %s != %s", Stargate.debug("Gate::Matches", String.format("Block Type Mismatch: %s != %s",
type, MaterialHelper.specifiersToMaterials(materialInLayout))); materialAtLocation, MaterialHelper.specifiersToMaterials(materialInLayout)));
return false; return false;
} }
} else { } else {
@@ -233,9 +231,9 @@ public class Gate {
* recognized, but still allowed in previous checks, verify the gate as long as all such instances of * recognized, but still allowed in previous checks, verify the gate as long as all such instances of
* the character correspond to the same material in the physical gate. All subsequent gates will also * the character correspond to the same material in the physical gate. All subsequent gates will also
* need to match the first verified gate. */ * need to match the first verified gate. */
this.characterMaterialMap.put(key, List.of(new BukkitMaterialSpecifier(type))); this.characterMaterialMap.put(key, List.of(new BukkitMaterialSpecifier(materialAtLocation)));
Stargate.debug("Gate::Matches", String.format("Missing layout material in %s. Using %s from the" + Stargate.debug("Gate::Matches", String.format("Missing layout material in %s. Using %s from the" +
" physical portal.", getFilename(), type)); " physical portal.", getFilename(), materialAtLocation));
} }
} }
return true; return true;
@@ -244,16 +242,16 @@ public class Gate {
/** /**
* Verifies that all entrances of a portal gate matches this gate type * Verifies that all entrances of a portal gate matches this gate type
* *
* @param topLeft <p>The top-left block of the portal's gate</p> * @param topLeft <p>The top-left block of this portal</p>
* @param facing <p>The direction the portal is facing</p> * @param yaw <p>The yaw when looking directly outwards</p>
* @param onCreate <p>Whether this is used in the context of creating a new gate</p> * @param onCreate <p>Whether this is used in the context of creating a new gate</p>
* @return <p>Whether this is used in the context of creating a new gate</p> * @return <p>Whether this is used in the context of creating a new gate</p>
*/ */
private boolean verifyGateEntrancesMatch(@NotNull Block topLeft, @NotNull BlockFace facing, boolean onCreate) { private boolean verifyGateEntrancesMatch(@NotNull BlockLocation topLeft, double yaw, boolean onCreate) {
Stargate.debug("verifyGateEntrancesMatch", String.valueOf(topLeft)); Stargate.debug("verifyGateEntrancesMatch", String.valueOf(topLeft));
for (BlockVector entranceVector : layout.getEntrances()) { for (RelativeBlockVector entranceVector : layout.getEntrances()) {
Stargate.debug("verifyGateEntrancesMatch", String.valueOf(entranceVector)); Stargate.debug("verifyGateEntrancesMatch", String.valueOf(entranceVector));
Material type = new SimpleVectorOperation(facing).getRealLocationBlock(topLeft, entranceVector).getType(); Material type = topLeft.getRelativeLocation(entranceVector, yaw).getType();
//Ignore entrance if it's air or water, and we're creating a new gate //Ignore entrance if it's air or water, and we're creating a new gate
if (onCreate && (type.isAir() || type == Material.WATER)) { if (onCreate && (type.isAir() || type == Material.WATER)) {

View File

@@ -1,6 +1,6 @@
package net.knarcraft.stargate.portal.property.gate; package net.knarcraft.stargate.portal.property.gate;
import org.bukkit.util.BlockVector; import net.knarcraft.stargate.container.RelativeBlockVector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -19,11 +19,11 @@ import java.util.List;
public class GateLayout { public class GateLayout {
private final Character[][] layout; private final Character[][] layout;
private final List<BlockVector> exits = new ArrayList<>(); private final List<RelativeBlockVector> exits = new ArrayList<>();
private BlockVector[] entrances = new BlockVector[0]; private RelativeBlockVector[] entrances = new RelativeBlockVector[0];
private BlockVector[] border = new BlockVector[0]; private RelativeBlockVector[] border = new RelativeBlockVector[0];
private BlockVector[] controls = new BlockVector[0]; private RelativeBlockVector[] controls = new RelativeBlockVector[0];
private BlockVector exitBlock = null; private RelativeBlockVector exitBlock = null;
/** /**
* Instantiates a new gate layout * Instantiates a new gate layout
@@ -53,7 +53,7 @@ public class GateLayout {
* @return <p>The locations of entrances for this gate</p> * @return <p>The locations of entrances for this gate</p>
*/ */
@NotNull @NotNull
public BlockVector[] getEntrances() { public RelativeBlockVector[] getEntrances() {
return entrances; return entrances;
} }
@@ -66,7 +66,7 @@ public class GateLayout {
* @return <p>The locations of border blocks for this gate</p> * @return <p>The locations of border blocks for this gate</p>
*/ */
@NotNull @NotNull
public BlockVector[] getBorder() { public RelativeBlockVector[] getBorder() {
return border; return border;
} }
@@ -76,7 +76,7 @@ public class GateLayout {
* @return <p>The exit block defined in the layout</p> * @return <p>The exit block defined in the layout</p>
*/ */
@Nullable @Nullable
public BlockVector getExit() { public RelativeBlockVector getExit() {
return exitBlock; return exitBlock;
} }
@@ -89,7 +89,7 @@ public class GateLayout {
* @return <p>All possible exits</p> * @return <p>All possible exits</p>
*/ */
@NotNull @NotNull
public List<BlockVector> getExits() { public List<RelativeBlockVector> getExits() {
return exits; return exits;
} }
@@ -102,7 +102,7 @@ public class GateLayout {
* @return <p>The locations of the control blocks for this gate</p> * @return <p>The locations of the control blocks for this gate</p>
*/ */
@NotNull @NotNull
public BlockVector[] getControls() { public RelativeBlockVector[] getControls() {
return controls; return controls;
} }
@@ -127,9 +127,9 @@ public class GateLayout {
* <p>This methods reads the layout and stores exits, entrances, border blocks and control blocks.</p> * <p>This methods reads the layout and stores exits, entrances, border blocks and control blocks.</p>
*/ */
private void readLayout() { private void readLayout() {
List<BlockVector> entranceList = new ArrayList<>(); List<RelativeBlockVector> entranceList = new ArrayList<>();
List<BlockVector> borderList = new ArrayList<>(); List<RelativeBlockVector> borderList = new ArrayList<>();
List<BlockVector> controlList = new ArrayList<>(); List<RelativeBlockVector> controlList = new ArrayList<>();
readLayout(controlList, entranceList, borderList); readLayout(controlList, entranceList, borderList);
@@ -145,9 +145,9 @@ public class GateLayout {
* @param entranceList <p>The list of entrances to save to</p> * @param entranceList <p>The list of entrances to save to</p>
* @param borderList <p>The list of border blocks to save to</p> * @param borderList <p>The list of border blocks to save to</p>
*/ */
private void readLayout(@NotNull List<BlockVector> controlList, private void readLayout(@NotNull List<RelativeBlockVector> controlList,
@NotNull List<BlockVector> entranceList, @NotNull List<RelativeBlockVector> entranceList,
@NotNull List<BlockVector> borderList) { @NotNull List<RelativeBlockVector> borderList) {
//Store the lowest opening for each column //Store the lowest opening for each column
int[] exitDepths = new int[layout[0].length]; int[] exitDepths = new int[layout[0].length];
@@ -166,7 +166,7 @@ public class GateLayout {
for (int x = 0; x < exitDepths.length; x++) { for (int x = 0; x < exitDepths.length; x++) {
//Ignore invalid exits //Ignore invalid exits
if (exitDepths[x] > 0) { if (exitDepths[x] > 0) {
this.exits.add(new BlockVector(x, exitDepths[x], 0)); this.exits.add(new RelativeBlockVector(x, exitDepths[x], 0));
} }
} }
} }
@@ -183,26 +183,26 @@ public class GateLayout {
* @param borderList <p>The list of border blocks to save to</p> * @param borderList <p>The list of border blocks to save to</p>
*/ */
private void parseLayoutCharacter(@NotNull Character key, int columnIndex, int rowIndex, int[] exitDepths, private void parseLayoutCharacter(@NotNull Character key, int columnIndex, int rowIndex, int[] exitDepths,
@NotNull List<BlockVector> controlList, @NotNull List<RelativeBlockVector> controlList,
@NotNull List<BlockVector> entranceList, @NotNull List<RelativeBlockVector> entranceList,
@NotNull List<BlockVector> borderList) { @NotNull List<RelativeBlockVector> borderList) {
//Add control blocks to the control block list //Add control blocks to the control block list
if (key.equals(GateHandler.getControlBlockCharacter())) { if (key.equals(GateHandler.getControlBlockCharacter())) {
controlList.add(new BlockVector(columnIndex, rowIndex, 0)); controlList.add(new RelativeBlockVector(columnIndex, rowIndex, 0));
} }
if (isOpening(key)) { if (isOpening(key)) {
//Register entrance //Register entrance
entranceList.add(new BlockVector(columnIndex, rowIndex, 0)); entranceList.add(new RelativeBlockVector(columnIndex, rowIndex, 0));
//Overwrite the lowest exit location for this column/x-coordinate //Overwrite the lowest exit location for this column/x-coordinate
exitDepths[columnIndex] = rowIndex; exitDepths[columnIndex] = rowIndex;
//Register exit if found //Register exit if found
if (key.equals(GateHandler.getExitCharacter())) { if (key.equals(GateHandler.getExitCharacter())) {
this.exitBlock = new BlockVector(columnIndex, rowIndex, 0); this.exitBlock = new RelativeBlockVector(columnIndex, rowIndex, 0);
} }
} else if (!key.equals(GateHandler.getAnythingCharacter())) { } else if (!key.equals(GateHandler.getAnythingCharacter())) {
//Register border block //Register border block
borderList.add(new BlockVector(columnIndex, rowIndex, 0)); borderList.add(new RelativeBlockVector(columnIndex, rowIndex, 0));
} }
} }

View File

@@ -39,7 +39,8 @@ public class PlayerTeleporter extends Teleporter {
* @param origin <p>The portal the player teleports from</p> * @param origin <p>The portal the player teleports from</p>
* @param event <p>The player move event triggering the event</p> * @param event <p>The player move event triggering the event</p>
*/ */
public void teleportPlayer(@NotNull Portal origin, @Nullable PlayerMoveEvent event) { public boolean teleportPlayer(@NotNull Portal origin, @Nullable PlayerMoveEvent event) {
boolean success = true;
double velocity = player.getVelocity().length(); double velocity = player.getVelocity().length();
List<Entity> passengers = player.getPassengers(); List<Entity> passengers = player.getPassengers();
@@ -47,12 +48,12 @@ public class PlayerTeleporter extends Teleporter {
if (!origin.equals(portal)) { if (!origin.equals(portal)) {
exit = triggerPortalEvent(origin, new StargatePlayerPortalEvent(player, origin, portal, exit)); exit = triggerPortalEvent(origin, new StargatePlayerPortalEvent(player, origin, portal, exit));
if (exit == null) { if (exit == null) {
return; return false;
} }
} }
//Calculate the exit velocity of the player //Calculate the exit velocity of the player
Vector newVelocityDirection = DirectionHelper.getDirectionVectorFromYaw(portal.getLocation().getYaw()); Vector newVelocityDirection = DirectionHelper.getDirectionVectorFromYaw(portal.getYaw());
Vector newVelocity = newVelocityDirection.multiply(velocity * Stargate.getGateConfig().getExitVelocity()); Vector newVelocity = newVelocityDirection.multiply(velocity * Stargate.getGateConfig().getExitVelocity());
//Load chunks to make sure not to teleport to the void //Load chunks to make sure not to teleport to the void
@@ -67,14 +68,18 @@ public class PlayerTeleporter extends Teleporter {
//If no event is passed in, assume it's a teleport, and act as such //If no event is passed in, assume it's a teleport, and act as such
if (event == null) { if (event == null) {
player.teleport(exit); success &= player.teleport(exit);
Stargate.debug("PlayerTeleporter::teleportPlayer", "Teleported player to " + exit);
} else { } else {
//Set the exit location of the event //Set the exit location of the event
success &= !event.isCancelled();
event.setTo(exit); event.setTo(exit);
Stargate.debug("PlayerTeleporter::teleportPlayer", "Overwrote movement event to " + exit);
} }
//Set the velocity of the teleported player after the teleportation is finished //Set the velocity of the teleported player after the teleportation is finished
Bukkit.getScheduler().scheduleSyncDelayedTask(Stargate.getInstance(), () -> player.setVelocity(newVelocity), 1); Bukkit.getScheduler().scheduleSyncDelayedTask(Stargate.getInstance(), () -> player.setVelocity(newVelocity), 1);
return success;
} }
} }

View File

@@ -1,19 +1,17 @@
package net.knarcraft.stargate.portal.teleporter; package net.knarcraft.stargate.portal.teleporter;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.container.BlockLocation;
import net.knarcraft.stargate.container.ChunkUnloadRequest; import net.knarcraft.stargate.container.ChunkUnloadRequest;
import net.knarcraft.stargate.container.RelativeBlockVector; import net.knarcraft.stargate.container.RelativeBlockVector;
import net.knarcraft.stargate.event.StargateTeleportEvent; import net.knarcraft.stargate.event.StargateTeleportEvent;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.transformation.SimpleVectorOperation;
import net.knarcraft.stargate.utility.DirectionHelper; import net.knarcraft.stargate.utility.DirectionHelper;
import net.knarcraft.stargate.utility.EntityHelper; import net.knarcraft.stargate.utility.EntityHelper;
import net.knarcraft.stargate.utility.TeleportHelper; import net.knarcraft.stargate.utility.TeleportHelper;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.Bisected; import org.bukkit.block.data.Bisected;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Slab; import org.bukkit.block.data.type.Slab;
@@ -21,7 +19,6 @@ import org.bukkit.entity.AbstractHorse;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -135,7 +132,7 @@ public abstract class Teleporter {
if (portal.getOptions().isBackwards()) { if (portal.getOptions().isBackwards()) {
adjust = 180; adjust = 180;
} }
float newYaw = (portal.getLocation().getYaw() + adjust) % 360; float newYaw = (portal.getYaw() + adjust) % 360;
Stargate.debug("Portal::adjustRotation", "Setting exit yaw to " + newYaw); Stargate.debug("Portal::adjustRotation", "Setting exit yaw to " + newYaw);
exit.setDirection(DirectionHelper.getDirectionVectorFromYaw(newYaw)); exit.setDirection(DirectionHelper.getDirectionVectorFromYaw(newYaw));
} }
@@ -177,7 +174,7 @@ public abstract class Teleporter {
if (openingWidth > 1) { if (openingWidth > 1) {
newOffset -= 0.5; newOffset -= 0.5;
} }
exitLocation = DirectionHelper.moveLocation(exitLocation, newOffset, 0, 0, portal.getLocation().getYaw()); exitLocation = DirectionHelper.moveLocation(exitLocation, newOffset, 0, 0, portal.getYaw());
//Move large entities further from the portal //Move large entities further from the portal
return moveExitLocationOutwards(exitLocation, entity); return moveExitLocationOutwards(exitLocation, entity);
@@ -206,7 +203,7 @@ public abstract class Teleporter {
if (entity instanceof AbstractHorse) { if (entity instanceof AbstractHorse) {
entityOffset += 1; entityOffset += 1;
} }
exitLocation = DirectionHelper.moveLocation(exitLocation, 0, 0, entityOffset, portal.getLocation().getYaw()); exitLocation = DirectionHelper.moveLocation(exitLocation, 0, 0, entityOffset, portal.getYaw());
} }
return exitLocation; return exitLocation;
} }
@@ -272,19 +269,17 @@ public abstract class Teleporter {
*/ */
@NotNull @NotNull
private Location getExit(@NotNull Entity entity) { private Location getExit(@NotNull Entity entity) {
Block exitLocation = null; Location exitLocation = null;
BlockVector relativeExit = portal.getGate().getLayout().getExit(); RelativeBlockVector relativeExit = portal.getGate().getLayout().getExit();
if (relativeExit != null) { if (relativeExit != null) {
Block exit = portal.getBlockAt(relativeExit); BlockLocation exit = portal.getBlockAt(relativeExit);
//Move one block out to prevent exiting inside the portal //Move one block out to prevent exiting inside the portal
BlockFace facing = portal.getLocation().getFacing(); float portalYaw = portal.getYaw();
if (portal.getOptions().isBackwards()) { if (portal.getOptions().isBackwards()) {
facing = facing.getOppositeFace(); portalYaw += 180;
} }
SimpleVectorOperation operation = new SimpleVectorOperation(facing); exitLocation = exit.getRelativeLocation(0D, 0D, 1, portalYaw);
exitLocation = operation.getRealLocationBlock(portal.getLocation().getTopLeft(),
new BlockVector(0, 0, 1));
double entitySize = EntityHelper.getEntityMaxSize(entity); double entitySize = EntityHelper.getEntityMaxSize(entity);
//Prevent exit suffocation for players riding horses or similar //Prevent exit suffocation for players riding horses or similar
@@ -310,8 +305,8 @@ public abstract class Teleporter {
@NotNull @NotNull
private List<Chunk> getChunksToLoad() { private List<Chunk> getChunksToLoad() {
List<Chunk> chunksToLoad = new ArrayList<>(); List<Chunk> chunksToLoad = new ArrayList<>();
for (BlockVector vector : portal.getGate().getLayout().getEntrances()) { for (RelativeBlockVector vector : portal.getGate().getLayout().getEntrances()) {
Block entranceLocation = portal.getBlockAt(vector); BlockLocation entranceLocation = portal.getBlockAt(vector);
Chunk chunk = entranceLocation.getChunk(); Chunk chunk = entranceLocation.getChunk();
//Make sure not to load chunks twice //Make sure not to load chunks twice
if (!chunksToLoad.contains(chunk)) { if (!chunksToLoad.contains(chunk)) {
@@ -320,7 +315,8 @@ public abstract class Teleporter {
//Get the chunk in front of the gate entrance //Get the chunk in front of the gate entrance
int blockOffset = portal.getOptions().isBackwards() ? -5 : 5; int blockOffset = portal.getOptions().isBackwards() ? -5 : 5;
Block fiveBlocksForward = entranceLocation.getRelative(portal.getLocation().getFacing(), blockOffset); Location fiveBlocksForward = DirectionHelper.moveLocation(entranceLocation, 0, 0, blockOffset,
portal.getYaw());
//Load the chunk five blocks forward to make sure the teleported entity will never spawn in unloaded chunks //Load the chunk five blocks forward to make sure the teleported entity will never spawn in unloaded chunks
Chunk forwardChunk = fiveBlocksForward.getChunk(); Chunk forwardChunk = fiveBlocksForward.getChunk();
if (!chunksToLoad.contains(forwardChunk)) { if (!chunksToLoad.contains(forwardChunk)) {

View File

@@ -56,7 +56,7 @@ public class VehicleTeleporter extends EntityTeleporter {
teleportingVehicle.setVelocity(new Vector()); teleportingVehicle.setVelocity(new Vector());
//Get new velocity //Get new velocity
Vector newVelocityDirection = DirectionHelper.getDirectionVectorFromYaw(portal.getLocation().getYaw()); Vector newVelocityDirection = DirectionHelper.getDirectionVectorFromYaw(portal.getYaw());
Vector newVelocity = newVelocityDirection.multiply(velocity); Vector newVelocity = newVelocityDirection.multiply(velocity);
//Call the StargateEntityPortalEvent to allow plugins to change destination //Call the StargateEntityPortalEvent to allow plugins to change destination

View File

@@ -2,12 +2,13 @@ package net.knarcraft.stargate.thread;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.container.BlockChangeRequest; import net.knarcraft.stargate.container.BlockChangeRequest;
import net.knarcraft.stargate.container.BlockLocation;
import net.knarcraft.stargate.container.ControlBlockUpdateRequest; import net.knarcraft.stargate.container.ControlBlockUpdateRequest;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.utility.DirectionHelper;
import net.knarcraft.stargate.utility.MaterialHelper; import net.knarcraft.stargate.utility.MaterialHelper;
import net.knarcraft.stargate.utility.PortalFileHelper; import net.knarcraft.stargate.utility.PortalFileHelper;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block;
/** /**
* This thread updates the signs and buttons of Stargates, if deemed necessary * This thread updates the signs and buttons of Stargates, if deemed necessary
@@ -25,7 +26,7 @@ public class ControlBlocksUpdateThread implements Runnable {
Portal portal = controlBlockUpdateRequest.portal(); Portal portal = controlBlockUpdateRequest.portal();
portal.drawSign(); portal.drawSign();
Block buttonLocation = portal.getLocation().getButtonBlock(); BlockLocation buttonLocation = PortalFileHelper.getButtonLocation(portal);
if (buttonLocation == null) { if (buttonLocation == null) {
return; return;
} }
@@ -41,7 +42,7 @@ public class ControlBlocksUpdateThread implements Runnable {
} else { } else {
//Replace button if the material is not a button //Replace button if the material is not a button
if (!MaterialHelper.isButtonCompatible(buttonLocation.getType())) { if (!MaterialHelper.isButtonCompatible(buttonLocation.getType())) {
PortalFileHelper.generatePortalButton(portal, portal.getLocation().getFacing()); PortalFileHelper.generatePortalButton(portal, DirectionHelper.getBlockFaceFromYaw(portal.getYaw()));
} }
} }
} }

View File

@@ -1,208 +0,0 @@
package net.knarcraft.stargate.transformation;
import org.bukkit.Axis;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
/**
* A class for performing rotational operations on vectors
*
* @author Kristian Knarvik
*/
@SuppressWarnings("unused")
public class SimpleVectorOperation {
private static final Map<BlockFace, Double> rotationAngles = new HashMap<>();
private static final Map<BlockFace, Vector> rotationAxes = new HashMap<>();
private static final Map<BlockFace, Axis> normalAxes = new HashMap<>();
private static final BlockFace defaultDirection = BlockFace.SOUTH;
private static final Axis defaultVerticalAxis = Axis.Y;
private final Axis normalAxis;
private boolean flipXAxis = false;
private final BlockFace facing;
/**
* Instantiates a vector operation to rotate vectors in the direction of a sign face
*
* @param signFace <p>The sign face of a gate's sign</p>
*/
public SimpleVectorOperation(@NotNull BlockFace signFace) {
if (normalAxes.isEmpty()) {
initializeIrisNormalAxes();
initializeOperations();
}
this.facing = signFace;
this.normalAxis = normalAxes.get(signFace);
}
/**
* Gets the block face of a sign given upon instantiation
*
* @return <p>The block face of a sign given upon instantiation</p>
*/
@NotNull
public BlockFace getFacing() {
return facing;
}
/**
* Gets the normal axis orthogonal to the opening plane
*
* <p>Said another way, get the axis going directly towards or away from a stargate's entrance.</p>
*
* @return <p>The normal axis orthogonal to the opening plane</p>
*/
@NotNull
public Axis getNormalAxis() {
return normalAxis;
}
/**
* Sets whether to flip the X- axis
*
* @param flipXAxis <p>Whether to flip the X-axis</p>
*/
public void setFlipXAxis(boolean flipXAxis) {
this.flipXAxis = flipXAxis;
}
/**
* Performs an operation from the real space to the vector space
*
* @param vector <p>The vector to perform the operation on</p>
* @return vector <p>A new vector with the operation applied</p>
*/
@NotNull
public Vector performToAbstractSpaceOperation(@NotNull Vector vector) {
Vector clone = vector.clone();
clone.rotateAroundAxis(rotationAxes.get(facing), rotationAngles.get(facing));
if (flipXAxis) {
clone.setX(-clone.getX());
}
return clone;
}
/**
* Performs an operation from the vector space to the real space
*
* @param vector <p>The vector to perform the inverse operation on</p>
* @return vector <p>A new vector with the operation applied</p>
*/
@NotNull
public Vector performToRealSpaceOperation(@NotNull Vector vector) {
Vector clone = vector.clone();
if (flipXAxis) {
clone.setX(-clone.getX());
}
return clone.rotateAroundAxis(rotationAxes.get(facing), -rotationAngles.get(facing));
}
/**
* Performs an operation from the vector space to the real space
*
* @param vector <p>The vector to perform the inverse operation on</p>
* @return vector <p>A new vector with the operation applied</p>
*/
@NotNull
public BlockVector performToRealSpaceOperation(@NotNull BlockVector vector) {
return performToRealSpaceOperation((Vector) vector).toBlockVector();
}
/**
* Gets the block vector pointing to the real location of the relative block vector
*
* @param topLeft <p>The vector of the top-left portal block</p>
* @param relative <p>The relative vector of a portal block</p>
* @return <p>The vector for the true location of the block in the real space</p>
*/
public BlockVector getRealLocationVector(@NotNull BlockVector topLeft, @NotNull BlockVector relative) {
return topLeft.clone().add(this.performToRealSpaceOperation(relative)).toBlockVector();
}
/**
* Gets the block pointing to the real location of the relative block vector
*
* @param topLeft <p>The top-left portal block</p>
* @param relative <p>The relative vector of a portal block</p>
* @return <p>The corresponding block</p>
*/
public Block getRealLocationBlock(@NotNull Block topLeft, @NotNull BlockVector relative) {
return topLeft.getLocation().clone().add(this.performToRealSpaceOperation(relative)).getBlock();
}
/**
* Initializes the operations used for rotating to each block-face
*/
private static void initializeOperations() {
Map<Axis, Vector> axisVectors = new HashMap<>();
axisVectors.put(Axis.Y, new Vector(0, 1, 0));
axisVectors.put(Axis.X, new Vector(1, 0, 0));
axisVectors.put(Axis.Z, new Vector(0, 0, 1));
//Use the cross product to find the correct axis
for (BlockFace face : normalAxes.keySet()) {
Vector crossProduct = face.getDirection().crossProduct(defaultDirection.getDirection());
if (face == defaultDirection || face == defaultDirection.getOppositeFace()) {
rotationAxes.put(face, axisVectors.get(defaultVerticalAxis));
} else if (Math.abs(crossProduct.getZ()) > 0) {
rotationAxes.put(face, axisVectors.get(Axis.Z));
} else if (Math.abs(crossProduct.getY()) > 0) {
rotationAxes.put(face, axisVectors.get(Axis.Y));
} else {
rotationAxes.put(face, axisVectors.get(Axis.X));
}
}
calculateRotations();
}
/**
* Calculates the required rotations based on the default rotation
*/
private static void calculateRotations() {
double halfRotation = Math.PI;
double quarterRotation = halfRotation / 2;
Vector defaultDirectionVector = defaultDirection.getDirection();
boolean defaultDirectionPositive = defaultDirectionVector.getX() + defaultDirectionVector.getY() +
defaultDirectionVector.getZ() > 0;
for (BlockFace blockFace : normalAxes.keySet()) {
if (defaultDirection == blockFace) {
//The default direction requires no rotation
rotationAngles.put(blockFace, 0d);
} else if (defaultDirection.getOppositeFace() == blockFace) {
//The opposite direction requires a half rotation
rotationAngles.put(blockFace, halfRotation);
} else {
//All the other used directions require a quarter rotation
Vector faceDirectionVector = blockFace.getDirection();
boolean faceDirectionPositive = faceDirectionVector.getX() + faceDirectionVector.getY() +
faceDirectionVector.getZ() > 0;
double rotation = defaultDirectionPositive && faceDirectionPositive ? quarterRotation : -quarterRotation;
rotationAngles.put(blockFace, rotation);
}
}
}
/**
* Initializes the iris normal axes corresponding to each block face
*/
private static void initializeIrisNormalAxes() {
normalAxes.put(BlockFace.EAST, Axis.Z);
normalAxes.put(BlockFace.WEST, Axis.Z);
normalAxes.put(BlockFace.NORTH, Axis.X);
normalAxes.put(BlockFace.SOUTH, Axis.X);
normalAxes.put(BlockFace.UP, Axis.Y);
normalAxes.put(BlockFace.DOWN, Axis.Y);
}
}

View File

@@ -2,6 +2,7 @@ package net.knarcraft.stargate.utility;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.config.ConfigOption; import net.knarcraft.stargate.config.ConfigOption;
import net.knarcraft.stargate.portal.PortalHandler;
import net.knarcraft.stargate.portal.property.gate.GateHandler; import net.knarcraft.stargate.portal.property.gate.GateHandler;
import org.bstats.bukkit.Metrics; import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimplePie; import org.bstats.charts.SimplePie;
@@ -39,7 +40,7 @@ public final class BStatsHelper {
Metrics metrics = new Metrics(plugin, pluginId); Metrics metrics = new Metrics(plugin, pluginId);
Map<ConfigOption, Object> configValues = Stargate.getStargateConfig().getConfigOptions(); Map<ConfigOption, Object> configValues = Stargate.getStargateConfig().getConfigOptions();
Map<String, List<String>> portalNetworks = PortalUtil.getAllPortalNetworks(); Map<String, List<String>> portalNetworks = PortalHandler.getAllPortalNetworks();
int totalPortals = 0; int totalPortals = 0;
for (List<String> portals : portalNetworks.values()) { for (List<String> portals : portalNetworks.values()) {
totalPortals += portals.size(); totalPortals += portals.size();

View File

@@ -4,6 +4,7 @@ import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.config.formatting.Message; import net.knarcraft.stargate.config.formatting.Message;
import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.config.formatting.SGFormatBuilder;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.portal.PortalHandler;
import net.knarcraft.stargate.portal.teleporter.PlayerTeleporter; import net.knarcraft.stargate.portal.teleporter.PlayerTeleporter;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
@@ -163,7 +164,7 @@ public final class BungeeHelper {
if (player == null) { if (player == null) {
bungeeQueue.put(playerUUID, destination); bungeeQueue.put(playerUUID, destination);
} else { } else {
Portal destinationPortal = PortalUtil.getBungeePortal(destination); Portal destinationPortal = PortalHandler.getBungeePortal(destination);
//If teleporting to an invalid portal, let the server decide where the player arrives //If teleporting to an invalid portal, let the server decide where the player arrives
if (destinationPortal == null) { if (destinationPortal == null) {
Stargate.logInfo(String.format("Bungee portal %s does not exist", destination)); Stargate.logInfo(String.format("Bungee portal %s does not exist", destination));

View File

@@ -1,14 +1,9 @@
package net.knarcraft.stargate.utility; package net.knarcraft.stargate.utility;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Directional;
import org.bukkit.block.data.type.Sign;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/** /**
* This class helps with direction-related calculations * This class helps with direction-related calculations
@@ -19,22 +14,6 @@ public final class DirectionHelper {
} }
/**
* Gets the direction the given block is facing
*
* @param block <p>The block to get the direction of</p>
* @return <p>The direction the block is facing, or null if the block is not directional</p>
*/
@Nullable
public static BlockFace getFacing(@NotNull Block block) {
BlockData blockData = block.getBlockData();
if (blockData instanceof Directional directional) {
return directional.getFacing();
} else {
return null;
}
}
/** /**
* Gets a yaw by comparing two locations * Gets a yaw by comparing two locations
* *
@@ -60,32 +39,6 @@ public final class DirectionHelper {
throw new IllegalArgumentException("Locations given are equal or at the same x and y axis"); throw new IllegalArgumentException("Locations given are equal or at the same x and y axis");
} }
/**
* Gets a block face by comparing two locations
*
* <p>The block face here is the direction an observer at the from location has to look to face the to location.
* The block face is only meant to be calculated for locations where both have either the same x value or the same
* z value. Equal locations, or locations with equal x and equal z will throw an exception.</p>
*
* @param fromLocation <p>The origin location</p>
* @param toLocation <p>The target location, which the block face will point towards</p>
* @return <p>The yaw pointing from the first location to the second location</p>
* @throws IllegalArgumentException <p>If the locations are the same, or equal except y</p>
*/
public static BlockFace getBlockFaceFromLocationDifference(@NotNull Location fromLocation, @NotNull Location toLocation) throws IllegalArgumentException {
Location difference = fromLocation.clone().subtract(toLocation.clone());
if (difference.getX() > 0) {
return BlockFace.WEST;
} else if (difference.getX() < 0) {
return BlockFace.EAST;
} else if (difference.getZ() > 0) {
return BlockFace.NORTH;
} else if (difference.getZ() < 0) {
return BlockFace.SOUTH;
}
throw new IllegalArgumentException("Locations given are equal or at the same x and y axis");
}
/** /**
* Gets a block face given a yaw value * Gets a block face given a yaw value
* *
@@ -113,23 +66,6 @@ public final class DirectionHelper {
} }
} }
/**
* Gets a yaw from the specified block face
*
* @param blockFace <p>The block face to convert into a yaw</p>
* @return <p>The yaw of the block face</p>
* @throws IllegalArgumentException <p>If the block face is not pointing to one of the four primary directions</p>
*/
public static double getYawFromBlockFace(@NotNull BlockFace blockFace) throws IllegalArgumentException {
return switch (blockFace) {
case SOUTH -> 0;
case WEST -> 90;
case NORTH -> 180;
case EAST -> 270;
default -> throw new IllegalArgumentException("Invalid block face given. It must be one of N,S,W,E");
};
}
/** /**
* Gets a direction vector given a yaw * Gets a direction vector given a yaw
* *
@@ -206,36 +142,6 @@ public final class DirectionHelper {
} }
} }
/**
* Gets this block location's parent block
*
* <p>The parent block is the block the item at this block location is attached to. Usually this is the block a
* sign or wall sign is attached to.</p>
*
* @return <p>This block location's parent block</p>
*/
@Nullable
public static Block getParent(@NotNull Block block) {
int offsetX = 0;
int offsetY = 0;
int offsetZ = 0;
BlockData blockData = block.getBlockData();
if (blockData instanceof Directional) {
//Get the offset of the block "behind" this block
BlockFace facing = ((Directional) blockData).getFacing().getOppositeFace();
offsetX = facing.getModX();
offsetZ = facing.getModZ();
} else if (blockData instanceof Sign) {
//Get offset the block beneath the sign
offsetY = -1;
} else {
return null;
}
return block.getRelative(offsetX, offsetY, offsetZ);
}
/** /**
* Normalizes a yaw to make it positive and no larger than 360 degrees * Normalizes a yaw to make it positive and no larger than 360 degrees
* *

View File

@@ -145,7 +145,8 @@ public final class PermissionHelper {
//If there is no destination, deny //If there is no destination, deny
Stargate.debug(route, "Portal has no destination"); Stargate.debug(route, "Portal has no destination");
deny = true; deny = true;
} else if (PermissionHelper.cannotAccessWorld(player, destination.getLocation().getWorld().getName())) { } else if (destination.getWorld() != null &&
PermissionHelper.cannotAccessWorld(player, destination.getWorld().getName())) {
//If the player does not have access to the portal's world, deny //If the player does not have access to the portal's world, deny
Stargate.debug(route, "Cannot access world"); Stargate.debug(route, "Cannot access world");
deny = true; deny = true;
@@ -218,7 +219,7 @@ public final class PermissionHelper {
* @return <p>False if the player should be allowed to access the world</p> * @return <p>False if the player should be allowed to access the world</p>
*/ */
public static boolean cannotAccessWorld(@NotNull Player player, @NotNull String world) { public static boolean cannotAccessWorld(@NotNull Player player, @NotNull String world) {
return hasPermission(player, Permission.ACCESS_WORLD, world); return !hasPermission(player, Permission.ACCESS_WORLD, world);
} }
/** /**

View File

@@ -2,8 +2,11 @@ package net.knarcraft.stargate.utility;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.container.BlockChangeRequest; import net.knarcraft.stargate.container.BlockChangeRequest;
import net.knarcraft.stargate.container.BlockLocation;
import net.knarcraft.stargate.container.ControlBlockUpdateRequest; import net.knarcraft.stargate.container.ControlBlockUpdateRequest;
import net.knarcraft.stargate.container.RelativeBlockVector;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.portal.PortalHandler;
import net.knarcraft.stargate.portal.PortalRegistry; import net.knarcraft.stargate.portal.PortalRegistry;
import net.knarcraft.stargate.portal.property.PortalLocation; import net.knarcraft.stargate.portal.property.PortalLocation;
import net.knarcraft.stargate.portal.property.PortalOptions; import net.knarcraft.stargate.portal.property.PortalOptions;
@@ -11,19 +14,16 @@ import net.knarcraft.stargate.portal.property.PortalOwner;
import net.knarcraft.stargate.portal.property.PortalStrings; import net.knarcraft.stargate.portal.property.PortalStrings;
import net.knarcraft.stargate.portal.property.gate.Gate; import net.knarcraft.stargate.portal.property.gate.Gate;
import net.knarcraft.stargate.portal.property.gate.GateHandler; import net.knarcraft.stargate.portal.property.gate.GateHandler;
import net.knarcraft.stargate.transformation.SimpleVectorOperation;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Directional; import org.bukkit.block.data.Directional;
import org.bukkit.block.data.Waterlogged; import org.bukkit.block.data.Waterlogged;
import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
@@ -57,12 +57,17 @@ public final class PortalFileHelper {
for (Portal portal : PortalRegistry.getAllPortals()) { for (Portal portal : PortalRegistry.getAllPortals()) {
//Skip portals in other worlds //Skip portals in other worlds
String worldName = portal.getLocation().getWorld().getName(); if (portal.getWorld() == null) {
if (!worldName.equalsIgnoreCase(world.getName())) { Stargate.logSevere(String.format("Could not save portal %s because its world is null",
continue; portal.getName()));
} else {
String worldName = portal.getWorld().getName();
if (!worldName.equalsIgnoreCase(world.getName())) {
continue;
}
//Save the portal
savePortal(bufferedWriter, portal);
} }
//Save the portal
savePortal(bufferedWriter, portal);
} }
bufferedWriter.close(); bufferedWriter.close();
@@ -80,19 +85,19 @@ public final class PortalFileHelper {
*/ */
private static void savePortal(@NotNull BufferedWriter bufferedWriter, @NotNull Portal portal) throws IOException { private static void savePortal(@NotNull BufferedWriter bufferedWriter, @NotNull Portal portal) throws IOException {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
Block button = portal.getStructure().getButton(); BlockLocation button = portal.getStructure().getButton();
//WARNING: Because of the primitive save format, any change in order will break everything! //WARNING: Because of the primitive save format, any change in order will break everything!
builder.append(portal.getName()).append(':'); builder.append(portal.getName()).append(':');
builder.append(portal.getLocation().getSignBlock()).append(':'); builder.append(portal.getSignLocation()).append(':');
builder.append((button != null) ? button.toString() : "").append(':'); builder.append((button != null) ? button.toString() : "").append(':');
//Add removes config values to keep indices consistent //Add removes config values to keep indices consistent
builder.append(0).append(':'); builder.append(0).append(':');
builder.append(0).append(':'); builder.append(0).append(':');
builder.append(DirectionHelper.getYawFromBlockFace(portal.getLocation().getFacing())).append(':'); builder.append(portal.getYaw()).append(':');
builder.append(portal.getLocation().getTopLeft()).append(':'); builder.append(portal.getTopLeft()).append(':');
builder.append(portal.getGate().getFilename()).append(':'); builder.append(portal.getGate().getFilename()).append(':');
//Only save the destination name if the gate is fixed as it doesn't matter otherwise //Only save the destination name if the gate is fixed as it doesn't matter otherwise
@@ -122,7 +127,11 @@ public final class PortalFileHelper {
builder.append(options.isHidden()).append(':'); builder.append(options.isHidden()).append(':');
builder.append(options.isAlwaysOn()).append(':'); builder.append(options.isAlwaysOn()).append(':');
builder.append(options.isPrivate()).append(':'); builder.append(options.isPrivate()).append(':');
builder.append(portal.getLocation().getWorld().getName()).append(':'); if (portal.getWorld() != null) {
builder.append(portal.getWorld().getName()).append(':');
} else {
builder.append(':');
}
builder.append(options.isFree()).append(':'); builder.append(options.isFree()).append(':');
builder.append(options.isBackwards()).append(':'); builder.append(options.isBackwards()).append(':');
builder.append(options.isShown()).append(':'); builder.append(options.isShown()).append(':');
@@ -220,9 +229,9 @@ public final class PortalFileHelper {
*/ */
private static void doPostLoadTasks(@NotNull World world, boolean needsToSaveDatabase) { private static void doPostLoadTasks(@NotNull World world, boolean needsToSaveDatabase) {
//Open any always-on portals. Do this here as it should be more efficient than in the loop. //Open any always-on portals. Do this here as it should be more efficient than in the loop.
PortalUtil.verifyAllPortals(); PortalHandler.verifyAllPortals();
int portalCount = PortalRegistry.getAllPortals().size(); int portalCount = PortalRegistry.getAllPortals().size();
int openCount = PortalUtil.openAlwaysOpenPortals(); int openCount = PortalHandler.openAlwaysOpenPortals();
//Print info about loaded stargates so that admins can see if all stargates loaded //Print info about loaded stargates so that admins can see if all stargates loaded
Stargate.logInfo(String.format("{%s} Loaded %d stargates with %d set as always-on", world.getName(), Stargate.logInfo(String.format("{%s} Loaded %d stargates with %d set as always-on", world.getName(),
@@ -233,8 +242,8 @@ public final class PortalFileHelper {
Stargate.debug("PortalFileHelper::doPostLoadTasks::update", Stargate.debug("PortalFileHelper::doPostLoadTasks::update",
String.format("Queueing portal sign/button updates for %s", world)); String.format("Queueing portal sign/button updates for %s", world));
for (Portal portal : PortalRegistry.getAllPortals()) { for (Portal portal : PortalRegistry.getAllPortals()) {
if (portal.isRegistered() && portal.getLocation().getWorld().equals(world) && if (portal.isRegistered() && portal.getWorld() != null && portal.getWorld().equals(world) &&
world.getWorldBorder().isInside(portal.getLocation().getSignBlock().getLocation())) { world.getWorldBorder().isInside(portal.getSignLocation())) {
Stargate.addControlBlockUpdateRequest(new ControlBlockUpdateRequest(portal)); Stargate.addControlBlockUpdateRequest(new ControlBlockUpdateRequest(portal));
Stargate.debug("UpdateSignsButtons", String.format("Queued sign and button updates for portal %s", Stargate.debug("UpdateSignsButtons", String.format("Queued sign and button updates for portal %s",
portal.getName())); portal.getName()));
@@ -258,13 +267,13 @@ public final class PortalFileHelper {
private static boolean loadPortal(@NotNull String[] portalData, @NotNull World world, int lineIndex) { private static boolean loadPortal(@NotNull String[] portalData, @NotNull World world, int lineIndex) {
//Load min. required portal data //Load min. required portal data
String name = portalData[0]; String name = portalData[0];
Block button = (!portalData[2].isEmpty()) ? getBlock(world, portalData[2]) : null; BlockLocation button = (!portalData[2].isEmpty()) ? new BlockLocation(world, portalData[2]) : null;
//Load the portal's location //Load the portal's location
PortalLocation portalLocation = new PortalLocation();
portalLocation.setSignLocation(new BlockLocation(world, portalData[1]));
PortalLocation portalLocation = new PortalLocation(getBlock(world, portalData[6]), portalLocation.setYaw(Float.parseFloat(portalData[5]));
DirectionHelper.getBlockFaceFromYaw(Float.parseFloat(portalData[5])), getBlock(world, portalData[1]), button); portalLocation.setTopLeft(new BlockLocation(world, portalData[6]));
//Check if the portal's gate type exists and is loaded //Check if the portal's gate type exists and is loaded
Gate gate = GateHandler.getGateByName(portalData[7]); Gate gate = GateHandler.getGateByName(portalData[7]);
@@ -286,11 +295,11 @@ public final class PortalFileHelper {
//Create the new portal //Create the new portal
PortalStrings portalStrings = new PortalStrings(name, network, destination); PortalStrings portalStrings = new PortalStrings(name, network, destination);
Portal portal = new Portal(portalLocation, button, portalStrings, gate, owner, Portal portal = new Portal(portalLocation, button, portalStrings, gate, owner,
PortalUtil.getPortalOptions(portalData)); PortalHandler.getPortalOptions(portalData));
//Register the portal, and close it in case it wasn't properly closed when the server stopped //Register the portal, and close it in case it wasn't properly closed when the server stopped
boolean buttonLocationChanged = updateButtonVector(portal); boolean buttonLocationChanged = updateButtonVector(portal);
PortalUtil.registerPortal(portal); PortalHandler.registerPortal(portal);
portal.getPortalOpener().closePortal(true); portal.getPortalOpener().closePortal(true);
return buttonLocationChanged; return buttonLocationChanged;
} }
@@ -298,16 +307,15 @@ public final class PortalFileHelper {
/** /**
* Decides the material to use for removing a portal's button/sign * Decides the material to use for removing a portal's button/sign
* *
* @param block <p>The location of the button/sign to replace</p> * @param location <p>The location of the button/sign to replace</p>
* @param portal <p>The portal the button/sign belongs to</p> * @param portal <p>The portal the button/sign belongs to</p>
* @return <p>The material to use for removing the button/sign</p> * @return <p>The material to use for removing the button/sign</p>
*/ */
@NotNull @NotNull
public static Material decideRemovalMaterial(@NotNull Block block, @NotNull Portal portal) { public static Material decideRemovalMaterial(@NotNull BlockLocation location, @NotNull Portal portal) {
//Get the blocks to each side of the location //Get the blocks to each side of the location
SimpleVectorOperation vectorOperation = portal.getLocation().getVectorOperation(); Location leftLocation = location.getRelativeLocation(-1, 0, 0, portal.getYaw());
Location leftLocation = block.getLocation().clone().add(vectorOperation.performToRealSpaceOperation(new Vector(-1, 0, 0))); Location rightLocation = location.getRelativeLocation(1, 0, 0, portal.getYaw());
Location rightLocation = block.getLocation().clone().add(vectorOperation.performToRealSpaceOperation(new Vector(1, 0, 0)));
//If the block is water or is waterlogged, assume the portal is underwater //If the block is water or is waterlogged, assume the portal is underwater
if (isUnderwater(leftLocation) || isUnderwater(rightLocation)) { if (isUnderwater(leftLocation) || isUnderwater(rightLocation)) {
@@ -341,12 +349,15 @@ public final class PortalFileHelper {
* @return <p>True if the calculated button location is not the same as the one in the portal file</p> * @return <p>True if the calculated button location is not the same as the one in the portal file</p>
*/ */
private static boolean updateButtonVector(@NotNull Portal portal) { private static boolean updateButtonVector(@NotNull Portal portal) {
for (BlockVector control : portal.getGate().getLayout().getControls()) { for (RelativeBlockVector control : portal.getGate().getLayout().getControls()) {
Block buttonLocation = portal.getLocation().getRelative(control.clone().add(new Vector(0, 0, 1)).toBlockVector()); BlockLocation controlLocation = portal.getLocation().getTopLeft().getRelativeLocation(control,
if (!buttonLocation.equals(portal.getLocation().getSignBlock())) { portal.getYaw());
portal.getLocation().setButtonBlock(buttonLocation); BlockLocation buttonLocation = controlLocation.getRelativeLocation(
new RelativeBlockVector(0, 0, 1), portal.getYaw());
if (!buttonLocation.equals(portal.getLocation().getSignLocation())) {
portal.getLocation().setButtonVector(control);
Block oldButtonLocation = portal.getStructure().getButton(); BlockLocation oldButtonLocation = portal.getStructure().getButton();
if (oldButtonLocation != null && !oldButtonLocation.equals(buttonLocation)) { if (oldButtonLocation != null && !oldButtonLocation.equals(buttonLocation)) {
Stargate.addControlBlockUpdateRequest(new BlockChangeRequest(oldButtonLocation, Material.AIR, null)); Stargate.addControlBlockUpdateRequest(new BlockChangeRequest(oldButtonLocation, Material.AIR, null));
portal.getStructure().setButton(buttonLocation); portal.getStructure().setButton(buttonLocation);
@@ -365,7 +376,7 @@ public final class PortalFileHelper {
*/ */
public static void generatePortalButton(@NotNull Portal portal, @NotNull BlockFace buttonFacing) { public static void generatePortalButton(@NotNull Portal portal, @NotNull BlockFace buttonFacing) {
//Go one block outwards to find the button's location rather than the control block's location //Go one block outwards to find the button's location rather than the control block's location
Block button = portal.getLocation().getButtonBlock(); BlockLocation button = getButtonLocation(portal);
// If the button location is null here, it is assumed that the button generation wasn't necessary // If the button location is null here, it is assumed that the button generation wasn't necessary
if (button == null) { if (button == null) {
@@ -379,24 +390,27 @@ public final class PortalFileHelper {
Directional buttonData = (Directional) Bukkit.createBlockData(buttonType); Directional buttonData = (Directional) Bukkit.createBlockData(buttonType);
buttonData.setFacing(buttonFacing); buttonData.setFacing(buttonFacing);
button.setBlockData(buttonData); button.getBlock().setBlockData(buttonData);
} }
portal.getStructure().setButton(button); portal.getStructure().setButton(button);
} }
/** /**
* Gets the block specified in the input * Gets the location of a portal's button
* *
* @param world <p>The world the block belongs to</p> * @param portal <p>The portal to find the button for</p>
* @param string <p>Comma-separated coordinate string</p> * @return <p>The location of the portal's button</p>
* @return <p>The specified block</p>
* @throws NumberFormatException <p>If non-numeric values are encountered</p>
*/ */
@NotNull @Nullable
private static Block getBlock(@NotNull World world, @NotNull String string) throws NumberFormatException { public static BlockLocation getButtonLocation(@NotNull Portal portal) {
String[] parts = string.split(","); BlockLocation topLeft = portal.getTopLeft();
return new Location(world, Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), RelativeBlockVector buttonVector = portal.getLocation().getButtonVector();
Integer.parseInt(parts[2])).getBlock();
if (buttonVector == null) {
return null;
}
return topLeft.getRelativeLocation(buttonVector.addOut(1), portal.getYaw());
} }
} }

View File

@@ -1,107 +0,0 @@
package net.knarcraft.stargate.utility;
import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.portal.PortalRegistry;
import net.knarcraft.stargate.portal.property.PortalOption;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* A helper class for saving and loading Stargates from or to YML files
*/
public final class PortalYMLHelper {
private PortalYMLHelper() {
}
/**
* Saves all portals
*
* @throws IOException <p>If unable to read or write a portal file</p>
*/
public void savePortals() throws IOException {
Map<World, File> worldFiles = new HashMap<>();
Map<World, FileConfiguration> configurations = new HashMap<>();
// Get and alter each configuration without saving
for (Portal portal : PortalRegistry.getAllPortals()) {
World world = portal.getLocation().getWorld();
File file = worldFiles.get(world);
FileConfiguration configuration = configurations.get(world);
if (file == null) {
file = new File(Stargate.getStargateConfig().getPortalFolder(), world.getUID() + ".yml");
worldFiles.put(world, file);
}
if (configuration == null) {
configuration = new YamlConfiguration();
configurations.put(world, configuration);
}
savePortal(portal, configuration);
}
// Save each configuration
for (Map.Entry<World, FileConfiguration> configuration : configurations.entrySet()) {
configuration.getValue().save(worldFiles.get(configuration.getKey()));
}
}
/**
* Saves the given portal
*
* @param portal <p>The portal to save</p>
*/
public void savePortal(@NotNull Portal portal, @NotNull FileConfiguration configuration) {
String root = portal.getNetwork() + "." + portal.getName();
ConfigurationSection portalSection = configuration.createSection(root);
portalSection.set("name", portal.getName());
portalSection.set("network", portal.getNetwork());
portalSection.set("destination", portal.getOptions().isFixed() ? portal.getDestinationName() : null);
portalSection.set("owner", portal.getOwner().getIdentifier());
portalSection.set("gate", portal.getGate().getFilename());
portalSection.set("topLeft", portal.getLocation().getTopLeft());
portalSection.set("signLocation", portal.getLocation().getSignBlock());
portalSection.set("buttonLocation", portal.getLocation().getButtonBlock());
portalSection.set("facing", portal.getLocation().getFacing());
for (PortalOption option : PortalOption.values()) {
portalSection.set("options." + option.getCharacterRepresentation(), portal.getOptions().checkOption(option));
}
}
@Nullable
public Portal loadPortal(@NotNull ConfigurationSection portalSection) {
/* PortalLocation location = new PortalLocation();
BlockLocation signLocation = (BlockLocation) portalSection.get("signLocation");
BlockLocation topLeft = (BlockLocation) portalSection.get("topLeft");
if (signLocation == null || topLeft == null) {
return null;
}
BlockFace facing = (BlockFace) Objects.requireNonNull(portalSection.get("facing"));
location.setSignLocation(signLocation).setButtonFacing(facing).setYaw(BlockFace.);
BlockLocation button;
PortalStrings portalStrings = new PortalStrings();
Gate gate = GateHandler.getGateByName();
PortalOwner owner;
Map<PortalOption, Boolean> options;
return new Portal(location, button, portalStrings, gate, owner, options);*/
return null;
}
}

View File

@@ -2,6 +2,7 @@ package net.knarcraft.stargate.utility;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.portal.PortalHandler;
import net.knarcraft.stargate.portal.PortalRegistry; import net.knarcraft.stargate.portal.PortalRegistry;
import net.knarcraft.stargate.portal.property.PortalOwner; import net.knarcraft.stargate.portal.property.PortalOwner;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
@@ -68,10 +69,10 @@ public final class UUIDMigrationHelper {
//Get the real portal from the copy and set UUID //Get the real portal from the copy and set UUID
for (Portal portalCopy : portals) { for (Portal portalCopy : portals) {
Portal portal = PortalUtil.getByName(portalCopy.getCleanName(), portalCopy.getCleanNetwork()); Portal portal = PortalHandler.getByName(portalCopy.getCleanName(), portalCopy.getCleanNetwork());
if (portal != null) { if (portal != null) {
portal.getOwner().setUUID(uniqueId); portal.getOwner().setUUID(uniqueId);
worldsToSave.add(portal.getLocation().getWorld()); worldsToSave.add(portal.getWorld());
} }
} }

View File

@@ -39,3 +39,4 @@ signToUse=to use gate
teleportMsg=Teleported teleportMsg=Teleported
vaultLoadError=Economy is enabled but Vault could not be loaded. Economy disabled vaultLoadError=Economy is enabled but Vault could not be loaded. Economy disabled
vaultLoaded=Vault v%version% found vaultLoaded=Vault v%version% found
teleportationFailed=Teleportation was cancelled or denied

View File

@@ -1,21 +0,0 @@
name: gdgdfg
network: central
ownerUUID: a62cd062-517c-4894-b00c-a5bfa8910369
gate: nether.gate
topLeft: -457,72,427
signLocation: -456,70,427
buttonLocation: -456,70,424
# Change this to block face?
facing: NORTH
options:
bungee: false
alwaysOn: false
hidden: false
private: false
free: false
backwards: false
show: false
noNetwork: false
random: false
quiet: false
invisible: false

View File

@@ -1,54 +0,0 @@
package net.knarcraft.stargate.container;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class RelativeBlockVectorTest {
@Test
public void addToVectorTest() {
int right = 5;
int down = 5;
int out = 3;
RelativeBlockVector relativeBlockVector = new RelativeBlockVector(right, down, out);
for (int i = 0; i < 1000; i++) {
int randomValue = getRandomNumber();
RelativeBlockVector newVector = relativeBlockVector.addRight(randomValue);
assertEquals(new RelativeBlockVector(right + randomValue, down, out), newVector);
newVector = relativeBlockVector.addOut(randomValue);
assertEquals(new RelativeBlockVector(right, down, out + randomValue), newVector);
newVector = relativeBlockVector.addDown(randomValue);
assertEquals(new RelativeBlockVector(right, down + randomValue, out), newVector);
}
}
@Test
public void invertTest() {
for (int i = 0; i < 1000; i++) {
int randomNumber1 = getRandomNumber();
int randomNumber2 = getRandomNumber();
int randomNumber3 = getRandomNumber();
RelativeBlockVector relativeBlockVector = new RelativeBlockVector(randomNumber1, randomNumber2,
randomNumber3);
RelativeBlockVector invertedBlockVector = new RelativeBlockVector(-randomNumber1, -randomNumber2,
-randomNumber3);
assertEquals(invertedBlockVector, relativeBlockVector.invert());
}
}
/**
* Gets a random number between -500 and 500
*
* @return <p>A random number between -500 and 500</p>
*/
private int getRandomNumber() {
return (int) ((Math.random() - 0.5) * 1000);
}
}