Improves button and material customization
Allows specifying a comma-separated list of materials and tags for a portal's button, open-material, closed-material and border blocks. A random value is used if more than one material is available.0 Uses the supplied button if any, instead of enforcing the specified button material. Always protects the button against block breaking. Fixes an incorrect permission result in the previous commit, which caused players stargate access to be inverted.
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
package net.knarcraft.stargate.config.material;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A specifier for a Bukkit material
|
||||
*/
|
||||
public class BukkitMaterialSpecifier implements MaterialSpecifier {
|
||||
|
||||
private final Material material;
|
||||
|
||||
/**
|
||||
* Instantiates a new material specifier
|
||||
*
|
||||
* @param material <p>The material to specify</p>
|
||||
*/
|
||||
public BukkitMaterialSpecifier(@NotNull Material material) {
|
||||
this.material = material;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String asString() {
|
||||
return this.material.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Set<Material> asMaterials() {
|
||||
return Set.of(this.material);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package net.knarcraft.stargate.config.material;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Tag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A specifier for a Bukkit material tag
|
||||
*/
|
||||
public class BukkitTagSpecifier implements MaterialSpecifier {
|
||||
|
||||
private final Tag<Material> tag;
|
||||
|
||||
/**
|
||||
* Instantiates a new tag specifier
|
||||
*
|
||||
* @param tag <p>The tag to specify</p>
|
||||
*/
|
||||
public BukkitTagSpecifier(@NotNull Tag<Material> tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String asString() {
|
||||
return "#" + this.tag.getKey().toString().replaceFirst("minecraft:", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<Material> asMaterials() {
|
||||
return this.tag.getValues();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package net.knarcraft.stargate.config.material;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* An interface describing a specifier for one or more Bukkit materials
|
||||
*/
|
||||
public interface MaterialSpecifier {
|
||||
|
||||
/**
|
||||
* Gets the string representation of the material specifier
|
||||
*
|
||||
* <p>This is used when saving the value to a gate file</p>
|
||||
*/
|
||||
@NotNull
|
||||
String asString();
|
||||
|
||||
/**
|
||||
* Gets all the materials the specifier specifies
|
||||
*
|
||||
* <p>This is used when registering gate materials</p>
|
||||
*/
|
||||
@NotNull
|
||||
Set<Material> asMaterials();
|
||||
|
||||
}
|
@@ -2,6 +2,7 @@ package net.knarcraft.stargate.listener;
|
||||
|
||||
import net.knarcraft.stargate.Stargate;
|
||||
import net.knarcraft.stargate.container.BlockChangeRequest;
|
||||
import net.knarcraft.stargate.container.BlockLocation;
|
||||
import net.knarcraft.stargate.event.StargateDestroyEvent;
|
||||
import net.knarcraft.stargate.portal.Portal;
|
||||
import net.knarcraft.stargate.portal.PortalCreator;
|
||||
@@ -139,6 +140,13 @@ public class BlockEventListener implements Listener {
|
||||
boolean deny = false;
|
||||
String denyMessage = "";
|
||||
|
||||
// Block breaking the button from breaking the entire Stargate
|
||||
if (portal.getStructure().getButton() != null && portal.getStructure().getButton().equals(
|
||||
new BlockLocation(event.getBlock()))) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
//Decide if the user can destroy the portal
|
||||
if (!PermissionHelper.canDestroyPortal(player, portal)) {
|
||||
denyMessage = Stargate.getString("denyMsg");
|
||||
|
@@ -181,7 +181,8 @@ public class PlayerEventListener implements Listener {
|
||||
//Check an additional block away for BungeeCord portals using END_PORTAL as its material
|
||||
entrancePortal = PortalHandler.getByAdjacentEntrance(toLocation);
|
||||
if (entrancePortal == null || !entrancePortal.getOptions().isBungee() ||
|
||||
entrancePortal.getGate().getPortalOpenBlock() != Material.END_PORTAL) {
|
||||
!MaterialHelper.specifiersToMaterials(
|
||||
entrancePortal.getGate().getPortalOpenMaterials()).contains(Material.END_PORTAL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@ package net.knarcraft.stargate.portal;
|
||||
import net.knarcraft.stargate.Stargate;
|
||||
import net.knarcraft.stargate.event.StargateActivateEvent;
|
||||
import net.knarcraft.stargate.event.StargateDeactivateEvent;
|
||||
import net.knarcraft.stargate.utility.ListHelper;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -10,7 +11,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* The portal activator activates/de-activates portals and keeps track of a portal's destinations
|
||||
@@ -77,7 +77,7 @@ public class PortalActivator {
|
||||
return null;
|
||||
}
|
||||
//Get one random destination
|
||||
String destination = destinations.get((new Random()).nextInt(destinations.size()));
|
||||
String destination = ListHelper.getRandom(destinations);
|
||||
return PortalHandler.getByName(Portal.cleanString(destination), portalNetwork);
|
||||
} else {
|
||||
//Just return the normal fixed destination
|
||||
|
@@ -12,8 +12,11 @@ import net.knarcraft.stargate.portal.property.gate.Gate;
|
||||
import net.knarcraft.stargate.portal.property.gate.GateHandler;
|
||||
import net.knarcraft.stargate.utility.DirectionHelper;
|
||||
import net.knarcraft.stargate.utility.EconomyHelper;
|
||||
import net.knarcraft.stargate.utility.ListHelper;
|
||||
import net.knarcraft.stargate.utility.MaterialHelper;
|
||||
import net.knarcraft.stargate.utility.PermissionHelper;
|
||||
import net.knarcraft.stargate.utility.PortalFileHelper;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -303,8 +306,12 @@ public class PortalCreator {
|
||||
} else {
|
||||
//Update the block type for the portal's opening to the closed block as the closed block can be anything,
|
||||
// not just air or water
|
||||
@NotNull List<Material> possibleMaterials = MaterialHelper.specifiersToMaterials(
|
||||
portal.getGate().getPortalClosedMaterials()).stream().toList();
|
||||
Material closedType = ListHelper.getRandom(possibleMaterials);
|
||||
|
||||
for (BlockLocation entrance : portal.getStructure().getEntrances()) {
|
||||
entrance.setType(portal.getGate().getPortalClosedBlock());
|
||||
entrance.setType(closedType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ import net.knarcraft.stargate.portal.property.PortalOption;
|
||||
import net.knarcraft.stargate.portal.property.PortalStructure;
|
||||
import net.knarcraft.stargate.portal.property.gate.Gate;
|
||||
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.World;
|
||||
@@ -445,8 +446,9 @@ public class PortalHandler {
|
||||
for (RelativeBlockVector control : portal.getGate().getLayout().getControls()) {
|
||||
Block block = portal.getBlockAt(control).getBlock();
|
||||
//Log control blocks not matching the gate layout
|
||||
if (!block.getType().equals(portal.getGate().getControlBlock())) {
|
||||
Stargate.debug("PortalHandler::destroyInvalidPortal", "Control Block Type == " +
|
||||
if (!MaterialHelper.specifiersToMaterials(portal.getGate().getControlBlockMaterials()).contains(
|
||||
block.getType())) {
|
||||
Stargate.debug("PortalHandler::unregisterInvalidPortal", "Control Block Type == " +
|
||||
block.getType().name());
|
||||
}
|
||||
}
|
||||
|
@@ -6,6 +6,8 @@ import net.knarcraft.stargate.container.BlockLocation;
|
||||
import net.knarcraft.stargate.event.StargateCloseEvent;
|
||||
import net.knarcraft.stargate.event.StargateOpenEvent;
|
||||
import net.knarcraft.stargate.portal.property.PortalOptions;
|
||||
import net.knarcraft.stargate.utility.ListHelper;
|
||||
import net.knarcraft.stargate.utility.MaterialHelper;
|
||||
import org.bukkit.Axis;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.Orientable;
|
||||
@@ -13,6 +15,8 @@ import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The portal opener is responsible for opening and closing a portal
|
||||
*/
|
||||
@@ -87,7 +91,10 @@ public class PortalOpener {
|
||||
}
|
||||
|
||||
//Get the material to change the opening to
|
||||
Material openType = portal.getGate().getPortalOpenBlock();
|
||||
@NotNull List<Material> possibleMaterials = MaterialHelper.specifiersToMaterials(
|
||||
portal.getGate().getPortalOpenMaterials()).stream().toList();
|
||||
Material openType = ListHelper.getRandom(possibleMaterials);
|
||||
|
||||
//Adjust orientation if applicable
|
||||
Axis axis = (openType.createBlockData() instanceof Orientable) ? portal.getLocation().getRotationAxis() : null;
|
||||
|
||||
@@ -168,9 +175,15 @@ public class PortalOpener {
|
||||
}
|
||||
|
||||
//Close the portal by requesting the opening blocks to change
|
||||
Material closedType = portal.getGate().getPortalClosedBlock();
|
||||
@NotNull List<Material> possibleMaterials = MaterialHelper.specifiersToMaterials(
|
||||
portal.getGate().getPortalClosedMaterials()).stream().toList();
|
||||
Material closedType = ListHelper.getRandom(possibleMaterials);
|
||||
|
||||
//Adjust orientation if applicable
|
||||
Axis axis = (closedType.createBlockData() instanceof Orientable) ? portal.getLocation().getRotationAxis() : null;
|
||||
|
||||
for (BlockLocation entrance : portal.getStructure().getEntrances()) {
|
||||
Stargate.addBlockChangeRequest(new BlockChangeRequest(entrance, closedType, null));
|
||||
Stargate.addBlockChangeRequest(new BlockChangeRequest(entrance, closedType, axis));
|
||||
}
|
||||
|
||||
//Update the portal state to make it actually closed
|
||||
|
@@ -1,10 +1,12 @@
|
||||
package net.knarcraft.stargate.portal.property.gate;
|
||||
|
||||
import net.knarcraft.stargate.Stargate;
|
||||
import net.knarcraft.stargate.config.material.BukkitMaterialSpecifier;
|
||||
import net.knarcraft.stargate.config.material.MaterialSpecifier;
|
||||
import net.knarcraft.stargate.container.BlockLocation;
|
||||
import net.knarcraft.stargate.container.RelativeBlockVector;
|
||||
import net.knarcraft.stargate.utility.MaterialHelper;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Tag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -13,6 +15,7 @@ import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -24,13 +27,12 @@ public class Gate {
|
||||
|
||||
private final String filename;
|
||||
private final GateLayout layout;
|
||||
private final Map<Character, Material> characterMaterialMap;
|
||||
private final Map<Character, Tag<Material>> characterTagMap;
|
||||
private final Map<Character, List<MaterialSpecifier>> characterMaterialMap;
|
||||
|
||||
//Gate materials
|
||||
private final Material portalOpenBlock;
|
||||
private final Material portalClosedBlock;
|
||||
private final Material portalButton;
|
||||
private final List<MaterialSpecifier> portalOpenMaterials;
|
||||
private final List<MaterialSpecifier> portalClosedMaterials;
|
||||
private final List<MaterialSpecifier> portalButtonMaterials;
|
||||
|
||||
//Economy information
|
||||
private final int useCost;
|
||||
@@ -41,34 +43,33 @@ public class Gate {
|
||||
/**
|
||||
* Instantiates a new gate
|
||||
*
|
||||
* @param filename <p>The name of the gate file, including extension</p>
|
||||
* @param layout <p>The gate layout defined in the gate file</p>
|
||||
* @param characterMaterialMap <p>The material types the different layout characters represent</p>
|
||||
* @param characterTagMap <p>The material tag types the different layout characters represent</p>
|
||||
* @param portalOpenBlock <p>The material to set the opening to when the portal is open</p>
|
||||
* @param portalClosedBlock <p>The material to set the opening to when the portal is closed</p>
|
||||
* @param portalButton <p>The material to use for the portal button</p>
|
||||
* @param useCost <p>The cost of using a portal with this gate layout (-1 to disable)</p>
|
||||
* @param createCost <p>The cost of creating a portal with this gate layout (-1 to disable)</p>
|
||||
* @param destroyCost <p>The cost of destroying a portal with this gate layout (-1 to disable)</p>
|
||||
* @param toOwner <p>Whether any payment should go to the owner of the gate, as opposed to just disappearing</p>
|
||||
* @param filename <p>The name of the gate file, including extension</p>
|
||||
* @param layout <p>The gate layout defined in the gate file</p>
|
||||
* @param characterMaterialsMap <p>The material types the different layout characters represent</p>
|
||||
* @param portalOpenMaterials <p>The material to set the opening to when the portal is open</p>
|
||||
* @param portalClosedMaterials <p>The material to set the opening to when the portal is closed</p>
|
||||
* @param portalButtonMaterials <p>The material to use for the portal button</p>
|
||||
* @param useCost <p>The cost of using a portal with this gate layout (-1 to disable)</p>
|
||||
* @param createCost <p>The cost of creating a portal with this gate layout (-1 to disable)</p>
|
||||
* @param destroyCost <p>The cost of destroying a portal with this gate layout (-1 to disable)</p>
|
||||
* @param toOwner <p>Whether any payment should go to the owner of the gate, as opposed to just disappearing</p>
|
||||
*/
|
||||
public Gate(@NotNull String filename, @NotNull GateLayout layout,
|
||||
@NotNull Map<Character, Material> characterMaterialMap,
|
||||
@NotNull Map<Character, Tag<Material>> characterTagMap, @NotNull Material portalOpenBlock,
|
||||
@NotNull Material portalClosedBlock, @NotNull Material portalButton, int useCost, int createCost,
|
||||
int destroyCost, boolean toOwner) {
|
||||
@NotNull Map<Character, List<MaterialSpecifier>> characterMaterialsMap,
|
||||
@NotNull List<MaterialSpecifier> portalOpenMaterials,
|
||||
@NotNull List<MaterialSpecifier> portalClosedMaterials,
|
||||
@NotNull List<MaterialSpecifier> portalButtonMaterials, int useCost, int createCost, int destroyCost,
|
||||
boolean toOwner) {
|
||||
this.filename = filename;
|
||||
this.layout = layout;
|
||||
this.characterMaterialMap = characterMaterialMap;
|
||||
this.portalOpenBlock = portalOpenBlock;
|
||||
this.portalClosedBlock = portalClosedBlock;
|
||||
this.portalButton = portalButton;
|
||||
this.characterMaterialMap = characterMaterialsMap;
|
||||
this.portalOpenMaterials = portalOpenMaterials;
|
||||
this.portalClosedMaterials = portalClosedMaterials;
|
||||
this.portalButtonMaterials = portalButtonMaterials;
|
||||
this.useCost = useCost;
|
||||
this.createCost = createCost;
|
||||
this.destroyCost = destroyCost;
|
||||
this.toOwner = toOwner;
|
||||
this.characterTagMap = characterTagMap;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,7 +88,7 @@ public class Gate {
|
||||
* @return <p>The character to material map</p>
|
||||
*/
|
||||
@NotNull
|
||||
public Map<Character, Material> getCharacterMaterialMap() {
|
||||
public Map<Character, List<MaterialSpecifier>> getCharacterMaterialMap() {
|
||||
return new HashMap<>(characterMaterialMap);
|
||||
}
|
||||
|
||||
@@ -98,18 +99,7 @@ public class Gate {
|
||||
* @return <p>True if the material is valid for control blocks</p>
|
||||
*/
|
||||
public boolean isValidControlBlock(@NotNull Material material) {
|
||||
return (getControlBlock() != null) ? getControlBlock().equals(material) :
|
||||
getControlBlockTag().isTagged(material);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the material tag used for this gate's control blocks
|
||||
*
|
||||
* @return <p>The material tag type used for control blocks</p>
|
||||
*/
|
||||
@NotNull
|
||||
public Tag<Material> getControlBlockTag() {
|
||||
return characterTagMap.get(GateHandler.getControlBlockCharacter());
|
||||
return getControlBlockMaterials().contains(new BukkitMaterialSpecifier(material));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,8 +107,8 @@ public class Gate {
|
||||
*
|
||||
* @return <p>The material type used for control blocks</p>
|
||||
*/
|
||||
@Nullable
|
||||
public Material getControlBlock() {
|
||||
@NotNull
|
||||
public List<MaterialSpecifier> getControlBlockMaterials() {
|
||||
return characterMaterialMap.get(GateHandler.getControlBlockCharacter());
|
||||
}
|
||||
|
||||
@@ -138,8 +128,8 @@ public class Gate {
|
||||
* @return <p>The block type to use for the opening when open</p>
|
||||
*/
|
||||
@NotNull
|
||||
public Material getPortalOpenBlock() {
|
||||
return portalOpenBlock;
|
||||
public List<MaterialSpecifier> getPortalOpenMaterials() {
|
||||
return portalOpenMaterials;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,8 +138,8 @@ public class Gate {
|
||||
* @return <p>The block type to use for the opening when closed</p>
|
||||
*/
|
||||
@NotNull
|
||||
public Material getPortalClosedBlock() {
|
||||
return portalClosedBlock;
|
||||
public List<MaterialSpecifier> getPortalClosedMaterials() {
|
||||
return portalClosedMaterials;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,8 +148,8 @@ public class Gate {
|
||||
* @return <p>The material to use for a portal's button if using this gate type</p>
|
||||
*/
|
||||
@NotNull
|
||||
public Material getPortalButton() {
|
||||
return portalButton;
|
||||
public List<MaterialSpecifier> getPortalButtonMaterials() {
|
||||
return portalButtonMaterials;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,35 +226,27 @@ public class Gate {
|
||||
* @return <p>True if all border blocks of the gate match the layout</p>
|
||||
*/
|
||||
private boolean verifyGateBorderMatches(@NotNull BlockLocation topLeft, double yaw) {
|
||||
Map<Character, Material> characterMaterialMap = new HashMap<>(this.characterMaterialMap);
|
||||
Map<Character, Tag<Material>> characterTagMap = new HashMap<>(this.characterTagMap);
|
||||
Map<Character, List<MaterialSpecifier>> characterMaterialMap = new HashMap<>(this.characterMaterialMap);
|
||||
for (RelativeBlockVector borderVector : layout.getBorder()) {
|
||||
int rowIndex = borderVector.right();
|
||||
int lineIndex = borderVector.down();
|
||||
Character key = layout.getLayout()[lineIndex][rowIndex];
|
||||
|
||||
Material materialInLayout = characterMaterialMap.get(key);
|
||||
Tag<Material> tagInLayout = characterTagMap.get(key);
|
||||
List<MaterialSpecifier> materialInLayout = characterMaterialMap.get(key);
|
||||
Material materialAtLocation = topLeft.getRelativeLocation(borderVector, yaw).getType();
|
||||
|
||||
if (materialInLayout != null) {
|
||||
if (materialAtLocation != materialInLayout) {
|
||||
if (!MaterialHelper.specifiersToMaterials(materialInLayout).contains(materialAtLocation)) {
|
||||
Stargate.debug("Gate::Matches", String.format("Block Type Mismatch: %s != %s",
|
||||
materialAtLocation, materialInLayout));
|
||||
return false;
|
||||
}
|
||||
} else if (tagInLayout != null) {
|
||||
if (!tagInLayout.isTagged(materialAtLocation)) {
|
||||
Stargate.debug("Gate::Matches", String.format("Block Type Mismatch: %s != %s",
|
||||
materialAtLocation, tagInLayout));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
/* This generally should not happen with proper checking, but just in case a material character is not
|
||||
* 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
|
||||
* need to match the first verified gate. */
|
||||
characterMaterialMap.put(key, materialAtLocation);
|
||||
characterMaterialMap.put(key, List.of(new BukkitMaterialSpecifier(materialAtLocation)));
|
||||
Stargate.debug("Gate::Matches", String.format("Missing layout material in %s. Using %s from the" +
|
||||
" physical portal.", getFilename(), materialAtLocation));
|
||||
}
|
||||
@@ -291,7 +273,8 @@ public class Gate {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type != portalClosedBlock && type != portalOpenBlock) {
|
||||
if (!MaterialHelper.specifiersToMaterials(portalClosedMaterials).contains(type) &&
|
||||
!MaterialHelper.specifiersToMaterials(portalOpenMaterials).contains(type)) {
|
||||
Stargate.debug("Gate::Matches", "Entrance/Exit Material Mismatch: " + type);
|
||||
return false;
|
||||
}
|
||||
@@ -311,9 +294,9 @@ public class Gate {
|
||||
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(new File(gateFolder, filename)));
|
||||
|
||||
//Save main material names
|
||||
writeConfig(bufferedWriter, "portal-open", portalOpenBlock.name());
|
||||
writeConfig(bufferedWriter, "portal-closed", portalClosedBlock.name());
|
||||
writeConfig(bufferedWriter, "button", portalButton.name());
|
||||
writeConfig(bufferedWriter, "portal-open", MaterialHelper.specifiersToString(portalOpenMaterials));
|
||||
writeConfig(bufferedWriter, "portal-closed", MaterialHelper.specifiersToString(portalClosedMaterials));
|
||||
writeConfig(bufferedWriter, "button", MaterialHelper.specifiersToString(portalButtonMaterials));
|
||||
|
||||
//Save the values necessary for economy
|
||||
saveEconomyValues(bufferedWriter);
|
||||
@@ -361,7 +344,7 @@ public class Gate {
|
||||
* @throws IOException <p>If unable to write to the buffered writer</p>
|
||||
*/
|
||||
private void saveFrameBlockType(@NotNull BufferedWriter bufferedWriter) throws IOException {
|
||||
for (Map.Entry<Character, Material> entry : this.characterMaterialMap.entrySet()) {
|
||||
for (Map.Entry<Character, List<MaterialSpecifier>> entry : this.characterMaterialMap.entrySet()) {
|
||||
Character key = entry.getKey();
|
||||
//Skip characters not part of the frame
|
||||
if (key.equals(GateHandler.getAnythingCharacter()) ||
|
||||
@@ -369,11 +352,7 @@ public class Gate {
|
||||
key.equals(GateHandler.getExitCharacter())) {
|
||||
continue;
|
||||
}
|
||||
saveFrameBlockType(key, entry.getValue().toString(), bufferedWriter);
|
||||
}
|
||||
for (Map.Entry<Character, Tag<Material>> entry : this.characterTagMap.entrySet()) {
|
||||
saveFrameBlockType(entry.getKey(), "#" + entry.getValue().getKey().toString().replaceFirst(
|
||||
"minecraft:", ""), bufferedWriter);
|
||||
saveFrameBlockType(key, MaterialHelper.specifiersToString(entry.getValue()), bufferedWriter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,8 @@
|
||||
package net.knarcraft.stargate.portal.property.gate;
|
||||
|
||||
import net.knarcraft.stargate.Stargate;
|
||||
import net.knarcraft.stargate.utility.GateReader;
|
||||
import net.knarcraft.stargate.config.material.BukkitMaterialSpecifier;
|
||||
import net.knarcraft.stargate.config.material.MaterialSpecifier;
|
||||
import net.knarcraft.stargate.utility.MaterialHelper;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
@@ -18,6 +19,8 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static net.knarcraft.stargate.utility.GateReader.generateLayoutMatrix;
|
||||
import static net.knarcraft.stargate.utility.GateReader.readGateConfig;
|
||||
@@ -94,20 +97,13 @@ public class GateHandler {
|
||||
private static void registerGate(@NotNull Gate gate) {
|
||||
gates.put(gate.getFilename(), gate);
|
||||
|
||||
Material blockId = gate.getControlBlock();
|
||||
if (blockId != null) {
|
||||
if (!controlBlocks.containsKey(blockId)) {
|
||||
controlBlocks.put(blockId, new ArrayList<>());
|
||||
Set<Material> blockTypes = MaterialHelper.specifiersToMaterials(gate.getControlBlockMaterials());
|
||||
for (Material material : blockTypes) {
|
||||
if (!controlBlocks.containsKey(material)) {
|
||||
controlBlocks.put(material, new ArrayList<>());
|
||||
}
|
||||
controlBlocks.get(blockId).add(gate);
|
||||
return;
|
||||
controlBlocks.get(material).add(gate);
|
||||
}
|
||||
|
||||
Tag<Material> materialTag = gate.getControlBlockTag();
|
||||
if (!controlBlockTags.containsKey(materialTag.getKey().toString())) {
|
||||
controlBlockTags.put(materialTag.getKey().toString(), new ArrayList<>());
|
||||
}
|
||||
controlBlockTags.get(materialTag.getKey().toString()).add(gate);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,24 +134,23 @@ public class GateHandler {
|
||||
private static Gate loadGate(@NotNull String fileName, @NotNull String parentFolder,
|
||||
@NotNull Scanner scanner) {
|
||||
List<List<Character>> design = new ArrayList<>();
|
||||
Map<Character, Material> characterMaterialMap = new HashMap<>();
|
||||
Map<Character, Tag<Material>> characterTagMap = new HashMap<>();
|
||||
Map<Character, List<MaterialSpecifier>> characterMaterialMap = new HashMap<>();
|
||||
Map<String, String> config = new HashMap<>();
|
||||
|
||||
//Initialize character to material map
|
||||
characterMaterialMap.put(ENTRANCE, Material.AIR);
|
||||
characterMaterialMap.put(EXIT, Material.AIR);
|
||||
characterMaterialMap.put(ANYTHING, Material.AIR);
|
||||
characterMaterialMap.put(ENTRANCE, List.of(new BukkitMaterialSpecifier(Material.AIR)));
|
||||
characterMaterialMap.put(EXIT, List.of(new BukkitMaterialSpecifier(Material.AIR)));
|
||||
characterMaterialMap.put(ANYTHING, List.of(new BukkitMaterialSpecifier(Material.AIR)));
|
||||
|
||||
//Read the file into appropriate lists and maps
|
||||
int columns = readGateFile(scanner, characterMaterialMap, characterTagMap, fileName, design, config);
|
||||
int columns = readGateFile(scanner, characterMaterialMap, fileName, design, config);
|
||||
if (columns < 0) {
|
||||
return null;
|
||||
}
|
||||
Character[][] layout = generateLayoutMatrix(design, columns);
|
||||
|
||||
//Create and validate the new gate
|
||||
Gate gate = createGate(config, fileName, layout, characterMaterialMap, characterTagMap);
|
||||
Gate gate = createGate(config, fileName, layout, characterMaterialMap);
|
||||
if (gate == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -172,28 +167,26 @@ public class GateHandler {
|
||||
* @param fileName <p>The name of the saved gate config file</p>
|
||||
* @param layout <p>The layout matrix of the new gate</p>
|
||||
* @param characterMaterialMap <p>A map between layout characters and the material to use</p>
|
||||
* @param materialTagMap <p>A map between layout characters and the material tags to use</p>
|
||||
* @return <p>A new gate, or null if the config is invalid</p>
|
||||
*/
|
||||
@Nullable
|
||||
private static Gate createGate(@NotNull Map<String, String> config, @NotNull String fileName,
|
||||
@NotNull Character[][] layout,
|
||||
@NotNull Map<Character, Material> characterMaterialMap,
|
||||
@NotNull Map<Character, Tag<Material>> materialTagMap) {
|
||||
@NotNull Map<Character, List<MaterialSpecifier>> characterMaterialMap) {
|
||||
//Read relevant material types
|
||||
Material portalOpenBlock = readGateConfig(config, fileName, "portal-open", defaultPortalBlockOpen);
|
||||
Material portalClosedBlock = readGateConfig(config, fileName, "portal-closed", defaultPortalBlockClosed);
|
||||
Material portalButton = readGateConfig(config, fileName, "button", defaultButton);
|
||||
List<MaterialSpecifier> portalOpenBlock = readGateConfig(config, fileName, "portal-open", defaultPortalBlockOpen);
|
||||
List<MaterialSpecifier> portalClosedBlock = readGateConfig(config, fileName, "portal-closed", defaultPortalBlockClosed);
|
||||
List<MaterialSpecifier> portalButton = readGateConfig(config, fileName, "button", defaultButton);
|
||||
|
||||
//Read economy values
|
||||
int useCost = GateReader.readGateConfig(config, fileName, "usecost");
|
||||
int createCost = GateReader.readGateConfig(config, fileName, "createcost");
|
||||
int destroyCost = GateReader.readGateConfig(config, fileName, "destroycost");
|
||||
int useCost = readGateConfig(config, fileName, "usecost");
|
||||
int createCost = readGateConfig(config, fileName, "createcost");
|
||||
int destroyCost = readGateConfig(config, fileName, "destroycost");
|
||||
boolean toOwner = (config.containsKey("toowner") ? Boolean.parseBoolean(config.get("toowner")) :
|
||||
Stargate.getEconomyConfig().sendPaymentToOwner());
|
||||
|
||||
//Create the new gate
|
||||
Gate gate = new Gate(fileName, new GateLayout(layout), characterMaterialMap, materialTagMap, portalOpenBlock,
|
||||
Gate gate = new Gate(fileName, new GateLayout(layout), characterMaterialMap, portalOpenBlock,
|
||||
portalClosedBlock, portalButton, useCost, createCost, destroyCost, toOwner);
|
||||
|
||||
if (!validateGate(gate, fileName)) {
|
||||
@@ -217,23 +210,23 @@ public class GateHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!MaterialHelper.isButtonCompatible(gate.getPortalButton())) {
|
||||
if (checkMaterialPredicateFail(gate.getPortalButtonMaterials(), MaterialHelper::isButtonCompatible)) {
|
||||
Stargate.logSevere(String.format(failString, "Gate button must be a type of button."));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!gate.getPortalOpenBlock().isBlock()) {
|
||||
if (checkMaterialPredicateFail(gate.getPortalOpenMaterials(), Material::isBlock)) {
|
||||
Stargate.logSevere(String.format(failString, "Gate open block must be a type of block."));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!gate.getPortalClosedBlock().isBlock()) {
|
||||
if (checkMaterialPredicateFail(gate.getPortalClosedMaterials(), Material::isBlock)) {
|
||||
Stargate.logSevere(String.format(failString, "Gate closed block must be a type of block."));
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Material material : gate.getCharacterMaterialMap().values()) {
|
||||
if (!material.isBlock()) {
|
||||
for (List<MaterialSpecifier> materialSpecifiers : gate.getCharacterMaterialMap().values()) {
|
||||
if (checkMaterialPredicateFail(materialSpecifiers, Material::isBlock)) {
|
||||
Stargate.logSevere(String.format(failString, "Every gate border block must be a type of block."));
|
||||
return false;
|
||||
}
|
||||
@@ -242,6 +235,25 @@ public class GateHandler {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a predicate is true for a list of material specifiers
|
||||
*
|
||||
* @param materialSpecifiers <p>The material specifiers to test</p>
|
||||
* @param predicate <p>The predicate to test</p>
|
||||
* @return <p>True if the predicate failed for any specified materials</p>
|
||||
*/
|
||||
private static boolean checkMaterialPredicateFail(@NotNull List<MaterialSpecifier> materialSpecifiers,
|
||||
@NotNull Predicate<Material> predicate) {
|
||||
Set<Material> closedMaterials = MaterialHelper.specifiersToMaterials(materialSpecifiers);
|
||||
for (Material material : closedMaterials) {
|
||||
if (!predicate.test(material)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all gates inside the given folder
|
||||
*
|
||||
|
@@ -1,10 +1,9 @@
|
||||
package net.knarcraft.stargate.utility;
|
||||
|
||||
import net.knarcraft.stargate.Stargate;
|
||||
import org.bukkit.Bukkit;
|
||||
import net.knarcraft.stargate.config.material.BukkitMaterialSpecifier;
|
||||
import net.knarcraft.stargate.config.material.MaterialSpecifier;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Tag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -26,15 +25,15 @@ public final class GateReader {
|
||||
*
|
||||
* @param scanner <p>The scanner to read from</p>
|
||||
* @param characterMaterialMap <p>The map of characters to store valid symbols in</p>
|
||||
* @param materialTagMap <p>The map of characters to store valid tag symbols in</p>
|
||||
* @param fileName <p>The filename of the loaded gate config file</p>
|
||||
* @param design <p>The list to store the loaded design/layout to</p>
|
||||
* @param config <p>The map of config values to store to</p>
|
||||
* @return <p>The column count/width of the loaded gate</p>
|
||||
*/
|
||||
public static int readGateFile(@NotNull Scanner scanner, @NotNull Map<Character, Material> characterMaterialMap,
|
||||
@NotNull Map<Character, Tag<Material>> materialTagMap, @NotNull String fileName,
|
||||
@NotNull List<List<Character>> design, Map<String, String> config) {
|
||||
public static int readGateFile(@NotNull Scanner scanner,
|
||||
@NotNull Map<Character, List<MaterialSpecifier>> characterMaterialMap,
|
||||
@NotNull String fileName, @NotNull List<List<Character>> design,
|
||||
@NotNull Map<String, String> config) {
|
||||
boolean designing = false;
|
||||
int columns = 0;
|
||||
try (scanner) {
|
||||
@@ -43,14 +42,14 @@ public final class GateReader {
|
||||
|
||||
if (designing) {
|
||||
//If we have reached the gate's layout/design, read it
|
||||
columns = readGateDesignLine(line, columns, characterMaterialMap, materialTagMap, fileName, design);
|
||||
columns = readGateDesignLine(line, columns, characterMaterialMap, fileName, design);
|
||||
if (columns < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (!line.isEmpty() && !line.startsWith("#")) {
|
||||
//Read a normal config value
|
||||
readGateConfigValue(line, characterMaterialMap, materialTagMap, config);
|
||||
readGateConfigValue(line, characterMaterialMap, config);
|
||||
} else if ((line.isEmpty()) || (!line.contains("=") && !line.startsWith("#"))) {
|
||||
//An empty line marks the start of the gate's layout/design
|
||||
designing = true;
|
||||
@@ -73,14 +72,12 @@ public final class GateReader {
|
||||
* @param line <p>The line to read</p>
|
||||
* @param maxColumns <p>The current max columns value of the design</p>
|
||||
* @param characterMaterialMap <p>The map between characters and the corresponding materials to use</p>
|
||||
* @param materialTagMap <p>The map between characters and the corresponding material tags to use</p>
|
||||
* @param fileName <p>The filename of the loaded gate config file</p>
|
||||
* @param design <p>The two-dimensional list to store the loaded design to</p>
|
||||
* @return <p>The new max columns value of the design</p>
|
||||
*/
|
||||
private static int readGateDesignLine(@NotNull String line, int maxColumns,
|
||||
@NotNull Map<Character, Material> characterMaterialMap,
|
||||
@NotNull Map<Character, Tag<Material>> materialTagMap,
|
||||
@NotNull Map<Character, List<MaterialSpecifier>> characterMaterialMap,
|
||||
@NotNull String fileName, @NotNull List<List<Character>> design) {
|
||||
List<Character> row = new ArrayList<>();
|
||||
|
||||
@@ -91,7 +88,7 @@ public final class GateReader {
|
||||
|
||||
for (Character symbol : line.toCharArray()) {
|
||||
//Refuse read gate designs with unknown characters
|
||||
if (symbol.equals('?') || (!characterMaterialMap.containsKey(symbol) && !materialTagMap.containsKey(symbol))) {
|
||||
if (symbol.equals('?') || !characterMaterialMap.containsKey(symbol)) {
|
||||
Stargate.logSevere(String.format("Could not load Gate %s - Unknown symbol '%s' in diagram", fileName,
|
||||
symbol));
|
||||
return -1;
|
||||
@@ -110,12 +107,11 @@ public final class GateReader {
|
||||
*
|
||||
* @param line <p>The line to read</p>
|
||||
* @param characterMaterialMap <p>The character to material map to store to</p>
|
||||
* @param materialTagMap <p>The character to material tag map to store to</p>
|
||||
* @param config <p>The config value map to store to</p>
|
||||
* @throws Exception <p>If an invalid material is encountered</p>
|
||||
*/
|
||||
private static void readGateConfigValue(@NotNull String line, @NotNull Map<Character, Material> characterMaterialMap,
|
||||
@NotNull Map<Character, Tag<Material>> materialTagMap,
|
||||
private static void readGateConfigValue(@NotNull String line,
|
||||
@NotNull Map<Character, List<MaterialSpecifier>> characterMaterialMap,
|
||||
@NotNull Map<String, String> config) throws Exception {
|
||||
String[] split = line.split("=");
|
||||
String key = split[0].trim();
|
||||
@@ -125,23 +121,12 @@ public final class GateReader {
|
||||
//Read a gate frame material
|
||||
Character symbol = key.charAt(0);
|
||||
|
||||
if (value.startsWith("#")) {
|
||||
String tagString = value.replaceFirst("#", "");
|
||||
Tag<Material> tag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, NamespacedKey.minecraft(tagString.toLowerCase()),
|
||||
Material.class);
|
||||
if (tag != null) {
|
||||
materialTagMap.put(symbol, tag);
|
||||
return;
|
||||
}
|
||||
List<MaterialSpecifier> materials = MaterialHelper.parseTagsAndMaterials(value);
|
||||
if (!materials.isEmpty()) {
|
||||
characterMaterialMap.put(symbol, materials);
|
||||
} else {
|
||||
Material material = Material.matchMaterial(value);
|
||||
if (material != null) {
|
||||
//Register the map between the read symbol and the corresponding material
|
||||
characterMaterialMap.put(symbol, material);
|
||||
return;
|
||||
}
|
||||
throw new Exception("Invalid material in line: " + line);
|
||||
}
|
||||
throw new Exception("Invalid material in line: " + line);
|
||||
} else {
|
||||
//Read a normal config value
|
||||
config.put(key, value);
|
||||
@@ -180,17 +165,17 @@ public final class GateReader {
|
||||
* @return <p>The material specified in the config, or the default material if it could not be read</p>
|
||||
*/
|
||||
@NotNull
|
||||
public static Material readGateConfig(@NotNull Map<String, String> config, @NotNull String fileName,
|
||||
@NotNull String key, @NotNull Material defaultMaterial) {
|
||||
public static List<MaterialSpecifier> readGateConfig(@NotNull Map<String, String> config, @NotNull String fileName,
|
||||
@NotNull String key, @NotNull Material defaultMaterial) {
|
||||
if (config.containsKey(key)) {
|
||||
Material material = Material.matchMaterial(config.get(key));
|
||||
if (material != null) {
|
||||
return material;
|
||||
List<MaterialSpecifier> materialSpecifiers = MaterialHelper.parseTagsAndMaterials(config.get(key));
|
||||
if (!materialSpecifiers.isEmpty()) {
|
||||
return materialSpecifiers;
|
||||
} else {
|
||||
Stargate.logWarning(String.format("Error reading %s: %s is not a material", fileName, key));
|
||||
}
|
||||
}
|
||||
return defaultMaterial;
|
||||
return List.of(new BukkitMaterialSpecifier(defaultMaterial));
|
||||
}
|
||||
|
||||
/**
|
||||
|
28
src/main/java/net/knarcraft/stargate/utility/ListHelper.java
Normal file
28
src/main/java/net/knarcraft/stargate/utility/ListHelper.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package net.knarcraft.stargate.utility;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* A helper class for dealing with lists
|
||||
*/
|
||||
public final class ListHelper {
|
||||
|
||||
private static final Random random = new Random();
|
||||
|
||||
private ListHelper() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a random item from a list
|
||||
*
|
||||
* @param list <p>The list to get an item from</p>
|
||||
* @param <T> <p>The type of item the list contains</p>
|
||||
* @return <p>A random item</p>
|
||||
*/
|
||||
public static <T> T getRandom(List<T> list) {
|
||||
return list.get(random.nextInt(list.size()));
|
||||
}
|
||||
|
||||
}
|
@@ -1,8 +1,19 @@
|
||||
package net.knarcraft.stargate.utility;
|
||||
|
||||
import net.knarcraft.stargate.config.material.BukkitMaterialSpecifier;
|
||||
import net.knarcraft.stargate.config.material.BukkitTagSpecifier;
|
||||
import net.knarcraft.stargate.config.material.MaterialSpecifier;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Tag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class helps decide properties of materials not already present in the Spigot API
|
||||
@@ -50,4 +61,80 @@ public final class MaterialHelper {
|
||||
return Tag.BUTTONS.isTagged(material) || isWallCoral(material) || isContainer(material);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String specifiersToString(@NotNull List<MaterialSpecifier> specifiers) {
|
||||
List<String> names = new ArrayList<>();
|
||||
for (MaterialSpecifier specifier : specifiers) {
|
||||
names.add(specifier.asString());
|
||||
}
|
||||
return String.join(",", names);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a list of material specifiers to a set of materials
|
||||
*
|
||||
* @param specifiers <p>The material specifiers to convert</p>
|
||||
* @return <p>The materials the specifiers represent</p>
|
||||
*/
|
||||
@NotNull
|
||||
public static Set<Material> specifiersToMaterials(@NotNull List<MaterialSpecifier> specifiers) {
|
||||
Set<Material> output = new HashSet<>();
|
||||
|
||||
for (MaterialSpecifier specifier : specifiers) {
|
||||
output.addAll(specifier.asMaterials());
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses all materials and material tags found in the input string
|
||||
*
|
||||
* @param input <p>The input string to parse</p>
|
||||
* @return <p>All material specifiers found</p>
|
||||
*/
|
||||
@NotNull
|
||||
public static List<MaterialSpecifier> parseTagsAndMaterials(@NotNull String input) {
|
||||
List<MaterialSpecifier> specifiers = new ArrayList<>();
|
||||
|
||||
// Nothing to parse
|
||||
if (input.isBlank()) {
|
||||
return specifiers;
|
||||
}
|
||||
|
||||
String[] parts;
|
||||
if (input.contains(",")) {
|
||||
parts = input.split(",");
|
||||
} else {
|
||||
parts = new String[]{input};
|
||||
}
|
||||
|
||||
for (String part : parts) {
|
||||
MaterialSpecifier materialSpecifier = parseTagOrMaterial(part.trim());
|
||||
if (materialSpecifier != null) {
|
||||
specifiers.add(materialSpecifier);
|
||||
}
|
||||
}
|
||||
|
||||
return specifiers;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static MaterialSpecifier parseTagOrMaterial(@NotNull String input) {
|
||||
if (input.startsWith("#")) {
|
||||
String tagString = input.replaceFirst("#", "").toLowerCase();
|
||||
Tag<Material> tag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, NamespacedKey.minecraft(tagString), Material.class);
|
||||
if (tag != null) {
|
||||
return new BukkitTagSpecifier(tag);
|
||||
}
|
||||
} else {
|
||||
Material material = Material.matchMaterial(input);
|
||||
if (material != null) {
|
||||
return new BukkitMaterialSpecifier(material);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -409,11 +409,13 @@ public final class PermissionHelper {
|
||||
}
|
||||
|
||||
//Player cannot access portal
|
||||
if (!PermissionHelper.cannotAccessPortal(player, entrancePortal, destination)) {
|
||||
if (PermissionHelper.cannotAccessPortal(player, entrancePortal, destination)) {
|
||||
if (!entrancePortal.getOptions().isSilent()) {
|
||||
Stargate.getMessageSender().sendErrorMessage(player, Stargate.getString("denyMsg"));
|
||||
}
|
||||
new PlayerTeleporter(entrancePortal, player).teleportPlayer(entrancePortal, event);
|
||||
Stargate.debug("PermissionHelper::playerCannotTeleport", "Closed portal because player is " +
|
||||
"missing necessary permissions");
|
||||
entrancePortal.getPortalOpener().closePortal(false);
|
||||
return true;
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
import static net.knarcraft.stargate.portal.PortalSignDrawer.markPortalWithInvalidGate;
|
||||
@@ -399,9 +400,15 @@ public final class PortalFileHelper {
|
||||
return;
|
||||
}
|
||||
|
||||
Directional buttonData = (Directional) Bukkit.createBlockData(portal.getGate().getPortalButton());
|
||||
buttonData.setFacing(buttonFacing);
|
||||
button.getBlock().setBlockData(buttonData);
|
||||
if (!MaterialHelper.isButtonCompatible(button.getType())) {
|
||||
@NotNull List<Material> possibleMaterials = MaterialHelper.specifiersToMaterials(
|
||||
portal.getGate().getPortalButtonMaterials()).stream().toList();
|
||||
Material buttonType = ListHelper.getRandom(possibleMaterials);
|
||||
|
||||
Directional buttonData = (Directional) Bukkit.createBlockData(buttonType);
|
||||
buttonData.setFacing(buttonFacing);
|
||||
button.getBlock().setBlockData(buttonData);
|
||||
}
|
||||
portal.getStructure().setButton(button);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user