From 616d45e7d9626ded62471169d75343ece51ab060 Mon Sep 17 00:00:00 2001
From: Thorinwasher
Date: Sat, 13 Jan 2024 18:24:26 +0100
Subject: [PATCH] Fixes issue #319
---
.../stargate/api/MetadataHolder.java | 14 +--
.../network/portal/AbstractPortal.java | 4 +-
.../network/portal/NetworkedPortal.java | 104 +++++++++++++-----
.../stargate/property/MetadataType.java | 7 ++
4 files changed, 93 insertions(+), 36 deletions(-)
create mode 100644 src/main/java/org/sgrewritten/stargate/property/MetadataType.java
diff --git a/src/main/java/org/sgrewritten/stargate/api/MetadataHolder.java b/src/main/java/org/sgrewritten/stargate/api/MetadataHolder.java
index 3fc44cf6..5b4db97c 100644
--- a/src/main/java/org/sgrewritten/stargate/api/MetadataHolder.java
+++ b/src/main/java/org/sgrewritten/stargate/api/MetadataHolder.java
@@ -29,27 +29,27 @@ public interface MetadataHolder {
/**
* Set the metadata of this instance
* @param data The data to set
- * @param plugin The name of the plugin this relates to
+ * @param field The name of the plugin or field this relates to
*/
- default void setMetadata(@Nullable JsonElement data, String plugin){
+ default void setMetadata(@Nullable JsonElement data, String field){
JsonObject metadata = loadMetadata();
if (data == null) {
- metadata.remove(plugin);
+ metadata.remove(field);
} else {
- metadata.add(plugin, data);
+ metadata.add(field, data);
}
this.setMetadata(metadata.toString());
}
/**
* Get the metadata of this instance
- * @param pluginName The name of the plugin this relates to
+ * @param field The name of the plugin or field this relates to
* @return The metadata of this instance
*/
@Nullable
- default JsonElement getMetadata(String pluginName){
+ default JsonElement getMetadata(String field){
JsonObject metaData = loadMetadata();
- return metaData.get(pluginName);
+ return metaData.get(field);
}
private @NotNull JsonObject loadMetadata(){
diff --git a/src/main/java/org/sgrewritten/stargate/network/portal/AbstractPortal.java b/src/main/java/org/sgrewritten/stargate/network/portal/AbstractPortal.java
index 6c625a01..0f36dd24 100644
--- a/src/main/java/org/sgrewritten/stargate/network/portal/AbstractPortal.java
+++ b/src/main/java/org/sgrewritten/stargate/network/portal/AbstractPortal.java
@@ -156,8 +156,8 @@ public GlobalPortalId getGlobalId() {
@Override
public List getPortalPosition(PositionType type) {
List positions = new ArrayList<>();
- gate.getPortalPositions().stream().filter((position) -> position.getPositionType() == type).forEach(
- (position) -> positions.add(gate.getLocation(position.getRelativePositionLocation())));
+ gate.getPortalPositions().stream().filter(position -> position.getPositionType() == type).forEach(
+ position -> positions.add(gate.getLocation(position.getRelativePositionLocation())));
return positions;
}
diff --git a/src/main/java/org/sgrewritten/stargate/network/portal/NetworkedPortal.java b/src/main/java/org/sgrewritten/stargate/network/portal/NetworkedPortal.java
index 7164acd6..981d13ac 100644
--- a/src/main/java/org/sgrewritten/stargate/network/portal/NetworkedPortal.java
+++ b/src/main/java/org/sgrewritten/stargate/network/portal/NetworkedPortal.java
@@ -1,10 +1,14 @@
package org.sgrewritten.stargate.network.portal;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonPrimitive;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
+import org.jetbrains.annotations.Nullable;
import org.sgrewritten.stargate.Stargate;
+import org.sgrewritten.stargate.action.SupplierAction;
import org.sgrewritten.stargate.api.config.ConfigurationOption;
import org.sgrewritten.stargate.api.event.portal.StargateAccessPortalEvent;
import org.sgrewritten.stargate.api.event.portal.StargateActivatePortalEvent;
@@ -25,6 +29,8 @@
import org.sgrewritten.stargate.exception.name.NameLengthException;
import org.sgrewritten.stargate.manager.StargatePermissionManager;
import org.sgrewritten.stargate.network.portal.formatting.HighlightingStyle;
+import org.sgrewritten.stargate.property.MetadataType;
+import org.sgrewritten.stargate.thread.ThreadHelper;
import org.sgrewritten.stargate.util.MessageUtils;
import java.util.ArrayList;
@@ -42,11 +48,13 @@
public class NetworkedPortal extends AbstractPortal {
private static final int NO_DESTINATION_SELECTED = -1;
+ private @Nullable String loadedDestination = null;
private int selectedDestination = NO_DESTINATION_SELECTED;
private List destinations = new ArrayList<>();
private boolean isActive;
+ private long previousDestinationSelectionTime;
/**
* Instantiates a new networked portal
@@ -59,8 +67,17 @@ public class NetworkedPortal extends AbstractPortal {
* @throws NameLengthException
*/
public NetworkedPortal(Network network, String name, Set flags, Set unrecognisedFlags, GateAPI gate, UUID ownerUUID,
- LanguageManager languageManager, StargateEconomyAPI economyAPI, String metaData) throws NameLengthException {
- super(network, name, flags, unrecognisedFlags, gate, ownerUUID, languageManager, economyAPI, metaData);
+ LanguageManager languageManager, StargateEconomyAPI economyAPI, String metadataString) throws NameLengthException {
+ super(network, name, flags, unrecognisedFlags, gate, ownerUUID, languageManager, economyAPI, metadataString);
+ if (!hasFlag(PortalFlag.ALWAYS_ON)) {
+ return;
+ }
+ JsonElement destinationElement = getMetadata(MetadataType.DESTINATION.name());
+ if (destinationElement == null) {
+ return;
+ }
+ this.loadedDestination = destinationElement.getAsString();
+ this.isActive = true;
}
@Override
@@ -91,10 +108,11 @@ public void onSignClick(PlayerInteractEvent event) {
return;
}
- selectedDestination = selectNewDestination(event.getAction(), previouslyActivated);
+ setSelectedDestination(selectNewDestination(event.getAction(), previouslyActivated));
this.updateState();
if (hasFlag(PortalFlag.ALWAYS_ON)) {
super.destination = getDestination();
+
}
}
@@ -110,18 +128,18 @@ private int selectNewDestination(Action action, boolean previouslyActivated) {
if (!ConfigurationHelper.getBoolean(ConfigurationOption.REMEMBER_LAST_DESTINATION)) {
return 0;
} else {
- if (selectedDestination == NO_DESTINATION_SELECTED) {
- selectedDestination = 0;
+ if (getSelectedDestination() == NO_DESTINATION_SELECTED) {
+ setSelectedDestination(0);
}
- return selectedDestination;
+ return getSelectedDestination();
}
}
if (action == Action.RIGHT_CLICK_BLOCK || action == Action.LEFT_CLICK_BLOCK) {
int step = (action == Action.RIGHT_CLICK_BLOCK) ? 1 : -1;
- return getNextDestination(step, selectedDestination);
+ return getNextDestination(step, getSelectedDestination());
}
- return selectedDestination;
+ return getSelectedDestination();
}
@Override
@@ -134,29 +152,37 @@ public void onButtonClick(PlayerInteractEvent event) {
@Override
public void updateState() {
- Portal destination = getDestination();
+ Portal destination;
+ if(hasFlag(PortalFlag.ALWAYS_ON) && this.loadedDestination != null){
+ destination = network.getPortal(this.loadedDestination);
+ this.loadedDestination = null;
+ } else {
+ destination = getDestination();
+ }
if (this.isActive && (destination == null || network.getPortal(destination.getName()) == null)) {
this.deactivate();
this.isActive = false; // in case of alwaysOn portal
this.close(true);
}
- this.selectedDestination = reloadSelectedDestination();
+ setSelectedDestination(reloadSelectedDestination(destination));
super.updateState();
}
/**
* Calculate the position of the portal that is selected, assuming the available destinations have changed.
*
+ * @param destination The previously selected portal
* @return The position of the selected portal in the destinations list
*/
- private int reloadSelectedDestination() {
- if (!this.isActive || super.activator == null) {
- return NO_DESTINATION_SELECTED;
+ private int reloadSelectedDestination(Portal destination){
+ Player player;
+ if (super.activator == null || hasFlag(PortalFlag.ALWAYS_ON)) {
+ player = null;
+ } else {
+ player = Bukkit.getPlayer(activator);
}
-
- Portal destination = this.destinations.get(this.selectedDestination);
- destinations = getDestinations(Bukkit.getPlayer(activator));
+ destinations = getDestinations(player);
if (destinations.contains(destination)) {
return destinations.indexOf(destination);
}
@@ -177,7 +203,7 @@ public void close(boolean force) {
public SignLine[] getDrawnControlLines() {
SignLine[] lines = new SignLine[4];
lines[0] = new PortalLine(super.colorDrawer.formatPortalName(this, HighlightingStyle.MINUS_SIGN), this, SignLineType.THIS_PORTAL);
- if (!this.isActive || this.selectedDestination == NO_DESTINATION_SELECTED) {
+ if (!this.isActive || this.getSelectedDestination() == NO_DESTINATION_SELECTED) {
lines[1] = new TextLine(super.colorDrawer.formatLine(super.languageManager.getString(TranslatableMessage.RIGHT_CLICK)));
lines[2] = new TextLine(super.colorDrawer.formatLine(super.languageManager.getString(TranslatableMessage.TO_USE)));
lines[3] = new NetworkLine(super.colorDrawer.formatNetworkName(network, network.getHighlightingStyle()), getNetwork());
@@ -189,10 +215,10 @@ public SignLine[] getDrawnControlLines() {
@Override
public Portal getDestination() {
- if (selectedDestination == NO_DESTINATION_SELECTED || selectedDestination >= destinations.size()) {
+ if (getSelectedDestination() == NO_DESTINATION_SELECTED || getSelectedDestination() >= destinations.size()) {
return null;
}
- return destinations.get(selectedDestination);
+ return destinations.get(getSelectedDestination());
}
/**
@@ -201,8 +227,8 @@ public Portal getDestination() {
* @param lines The sign lines to update
*/
private void drawActiveSign(SignLine[] lines) {
- int destinationIndex = selectedDestination % 3;
- int firstDestination = selectedDestination - destinationIndex;
+ int destinationIndex = getSelectedDestination() % 3;
+ int firstDestination = getSelectedDestination() - destinationIndex;
int maxLength = destinations.size();
for (int lineIndex = 0; lineIndex < 3; lineIndex++) {
int destination = lineIndex + firstDestination;
@@ -240,17 +266,20 @@ private void drawDestination(int lineIndex, int destination, int destinationInde
* The destinations available to the player
*
*/
- private List getDestinations(Player player) {
+ private List getDestinations(@Nullable Player player) {
+ List availablePortals;
if (player == null) {
- return new ArrayList<>();
+ availablePortals = new ArrayList<>(network.getAllPortals().stream().map(Portal::getId).toList());
+ availablePortals.remove(this.getId());
+ } else {
+ availablePortals = new ArrayList<>(network.getAvailablePortals(player, this));
}
- List availablePortals = new ArrayList<>(network.getAvailablePortals(player, this));
Collections.sort(availablePortals);
- List destinations = new ArrayList<>();
+ List output = new ArrayList<>();
for (String name : availablePortals) {
- destinations.add(network.getPortal(name));
+ output.add(network.getPortal(name));
}
- return destinations;
+ return output;
}
/**
@@ -356,5 +385,26 @@ protected void deactivate() {
super.deactivate();
}
+ private void setSelectedDestination(int selectedDestination) {
+ if (hasFlag(PortalFlag.ALWAYS_ON)) {
+ final long currentTime = System.currentTimeMillis();
+ this.previousDestinationSelectionTime = currentTime;
+ Bukkit.getScheduler().runTaskLater(Stargate.getInstance(), () -> {
+ Portal destination = getDestination();
+ if (currentTime == previousDestinationSelectionTime && destination != null) {
+ /*
+ * setSelectedDestination(int) can be called multiple times within the same millisecond, this avoids
+ * duplicate unnecessary calls
+ */
+ previousDestinationSelectionTime = -1;
+ ThreadHelper.callAsynchronously(() -> super.setMetadata(new JsonPrimitive(destination.getId()), MetadataType.DESTINATION.name()));
+ }
+ },20);
+ }
+ this.selectedDestination = selectedDestination;
+ }
+ private int getSelectedDestination() {
+ return this.selectedDestination;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/org/sgrewritten/stargate/property/MetadataType.java b/src/main/java/org/sgrewritten/stargate/property/MetadataType.java
new file mode 100644
index 00000000..8a7a2aee
--- /dev/null
+++ b/src/main/java/org/sgrewritten/stargate/property/MetadataType.java
@@ -0,0 +1,7 @@
+package org.sgrewritten.stargate.property;
+
+import javax.print.attribute.standard.Destination;
+
+public enum MetadataType {
+ DESTINATION
+}