Fix sign handling for 1.14

- Setup modules to load different classes for different Bukkit/Spigot versions
- Create BukkitHandler to get/set the sign facing and get the block it is attached to
- Fix `/as addsign` to use new sign methods
- Fix sign updates to use new sign methods
- Implement full forwards and backwards compatibility of the saved sign material type
    - On Bukkit 1.12 and lower all special wood types are translated to the standard sign
    - On Bukkit 1.13 the internal sign name is translated (and special wood types to the standard one)
    - On Bukkit 1.14 the signs of 1.13- are translated to the OAK variants
- Cleanup the .gitignore files inside of the module folders
This commit is contained in:
Thijs Wiefferink 2019-06-23 21:53:48 +02:00
parent fe131dc157
commit 4cda8a9292
27 changed files with 505 additions and 121 deletions

2
.gitignore vendored
View File

@ -1,5 +1,5 @@
# Maven stuff # Maven stuff
/target target
.project .project
.metadata .metadata

1
AreaShop/.gitignore vendored
View File

@ -1 +0,0 @@
/target

View File

@ -17,9 +17,7 @@
<dependency> <dependency>
<groupId>org.bukkit</groupId> <groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId> <artifactId>craftbukkit</artifactId>
<scope>system</scope> <version>1.14.2-R0.1-SNAPSHOT</version>
<version>any</version>
<systemPath>${project.basedir}/../dependencies/craftbukkit-1.7.9-R0.2-SNAPSHOT.jar</systemPath>
<type>jar</type> <type>jar</type>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
@ -63,6 +61,22 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<!-- Bukkit api implementations -->
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-bukkit-1_12</artifactId>
<version>latest</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-bukkit-1_13</artifactId>
<version>latest</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- WorldGuard implementations --> <!-- WorldGuard implementations -->
<dependency> <dependency>
<groupId>me.wiefferink</groupId> <groupId>me.wiefferink</groupId>

View File

@ -4,6 +4,7 @@ import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin; import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.managers.RegionManager; import com.sk89q.worldguard.protection.managers.RegionManager;
import me.wiefferink.areashop.interfaces.AreaShopInterface; import me.wiefferink.areashop.interfaces.AreaShopInterface;
import me.wiefferink.areashop.interfaces.BukkitInterface;
import me.wiefferink.areashop.interfaces.WorldEditInterface; import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldGuardInterface; import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.listeners.PlayerLoginLogoutListener; import me.wiefferink.areashop.listeners.PlayerLoginLogoutListener;
@ -54,6 +55,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
private WorldGuardInterface worldGuardInterface = null; private WorldGuardInterface worldGuardInterface = null;
private WorldEditPlugin worldEdit = null; private WorldEditPlugin worldEdit = null;
private WorldEditInterface worldEditInterface = null; private WorldEditInterface worldEditInterface = null;
private BukkitInterface bukkitInterface = null;
private FileManager fileManager = null; private FileManager fileManager = null;
private LanguageManager languageManager = null; private LanguageManager languageManager = null;
private CommandManager commandManager = null; private CommandManager commandManager = null;
@ -294,12 +296,12 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
// Load WorldEdit // Load WorldEdit
try { try {
final Class<?> clazz = Class.forName("me.wiefferink.areashop.handlers." + weVersion); Class<?> clazz = Class.forName("me.wiefferink.areashop.handlers." + weVersion);
// Check if we have a NMSHandler class at that location. // Check if we have a NMSHandler class at that location.
if(WorldEditInterface.class.isAssignableFrom(clazz)) { // Make sure it actually implements WorldEditInterface if(WorldEditInterface.class.isAssignableFrom(clazz)) { // Make sure it actually implements WorldEditInterface
worldEditInterface = (WorldEditInterface)clazz.getConstructor(AreaShopInterface.class).newInstance(this); // Set our handler worldEditInterface = (WorldEditInterface)clazz.getConstructor(AreaShopInterface.class).newInstance(this); // Set our handler
} }
} catch(final Exception e) { } catch(Exception e) {
error("Could not load the handler for WorldEdit (tried to load " + weVersion + "), report this problem to the author: " + ExceptionUtils.getStackTrace(e)); error("Could not load the handler for WorldEdit (tried to load " + weVersion + "), report this problem to the author: " + ExceptionUtils.getStackTrace(e));
error = true; error = true;
weVersion = null; weVersion = null;
@ -307,17 +309,35 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
// Load WorldGuard // Load WorldGuard
try { try {
final Class<?> clazz = Class.forName("me.wiefferink.areashop.handlers." + wgVersion); Class<?> clazz = Class.forName("me.wiefferink.areashop.handlers." + wgVersion);
// Check if we have a NMSHandler class at that location. // Check if we have a NMSHandler class at that location.
if(WorldGuardInterface.class.isAssignableFrom(clazz)) { // Make sure it actually implements WorldGuardInterface if(WorldGuardInterface.class.isAssignableFrom(clazz)) { // Make sure it actually implements WorldGuardInterface
worldGuardInterface = (WorldGuardInterface)clazz.getConstructor(AreaShopInterface.class).newInstance(this); // Set our handler worldGuardInterface = (WorldGuardInterface)clazz.getConstructor(AreaShopInterface.class).newInstance(this); // Set our handler
} }
} catch(final Exception e) { } catch(Exception e) {
error("Could not load the handler for WorldGuard (tried to load " + wgVersion + "), report this problem to the author:" + ExceptionUtils.getStackTrace(e)); error("Could not load the handler for WorldGuard (tried to load " + wgVersion + "), report this problem to the author:" + ExceptionUtils.getStackTrace(e));
error = true; error = true;
wgVersion = null; wgVersion = null;
} }
// Load Bukkit implementation
String bukkitHandler;
try {
Class.forName("org.bukkit.block.data.type.WallSign");
bukkitHandler = "1_13";
} catch (ClassNotFoundException e) {
bukkitHandler = "1_12";
}
try {
Class<?> clazz = Class.forName("me.wiefferink.areashop.handlers.BukkitHandler" + bukkitHandler);
bukkitInterface = (BukkitInterface)clazz.getConstructor(AreaShopInterface.class).newInstance(this);
} catch (Exception e) {
error("Could not load the Bukkit handler (used for sign updates), tried to load:", bukkitHandler + ", report this problem to the author:", ExceptionUtils.getStackTrace(e));
error = true;
bukkitHandler = null;
}
// Check if Vault is present // Check if Vault is present
if(getServer().getPluginManager().getPlugin("Vault") == null) { if(getServer().getPluginManager().getPlugin("Vault") == null) {
error("Vault plugin is not present or has not loaded correctly"); error("Vault plugin is not present or has not loaded correctly");
@ -332,10 +352,13 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
// Print loaded version of WG and WE in debug // Print loaded version of WG and WE in debug
if(wgVersion != null) { if(wgVersion != null) {
AreaShop.debug("Loaded WorldGuardHandler", wgVersion, "(raw version:" + rawWgVersion + ", major:" + major + ", minor:" + minor + ", fixes:" + fixes + ", build:" + build + ")"); AreaShop.debug("Loaded ", wgVersion, "(raw version:" + rawWgVersion + ", major:" + major + ", minor:" + minor + ", fixes:" + fixes + ", build:" + build + ", fawe:" + fawe + ")");
} }
if(weVersion != null) { if(weVersion != null) {
AreaShop.debug("Loaded WorldEditHandler", weVersion, "(raw version:" + rawWeVersion + ", beta:" + weBeta + ")"); AreaShop.debug("Loaded ", weVersion, "(raw version:" + rawWeVersion + ", beta:" + weBeta + ")");
}
if(bukkitHandler != null) {
AreaShop.debug("Loaded BukkitHandler", bukkitHandler);
} }
setupLanguageManager(); setupLanguageManager();
@ -550,6 +573,14 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
return languageManager; return languageManager;
} }
/**
* Get the BukkitHandler, for sign interactions.
* @return BukkitHandler
*/
public BukkitInterface getBukkitHandler() {
return this.bukkitInterface;
}
/** /**
* Function to get the CommandManager. * Function to get the CommandManager.
* @return the CommandManager * @return the CommandManager

View File

@ -9,7 +9,6 @@ import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.material.Sign;
import org.bukkit.util.BlockIterator; import org.bukkit.util.BlockIterator;
import java.util.ArrayList; import java.util.ArrayList;
@ -77,7 +76,6 @@ public class AddsignCommand extends CommandAreaShop {
} }
region = regions.get(0); region = regions.get(0);
} }
Sign sign = (Sign)block.getState().getData();
String profile = null; String profile = null;
if(args.length > 2) { if(args.length > 2) {
profile = args[2]; profile = args[2];
@ -93,7 +91,7 @@ public class AddsignCommand extends CommandAreaShop {
return; return;
} }
region.getSignsFeature().addSign(block.getLocation(), block.getType(), sign.getFacing(), profile); region.getSignsFeature().addSign(block.getLocation(), block.getType(), plugin.getBukkitHandler().getSignFacing(block), profile);
if(profile == null) { if(profile == null) {
plugin.message(sender, "addsign-success", region); plugin.message(sender, "addsign-success", region);
} else { } else {

View File

@ -84,7 +84,7 @@ public class RegionSign {
} }
/** /**
* Get the facing of the sign. * Get the facing of the sign as saved in the config.
* @return BlockFace the sign faces, or null if unknown * @return BlockFace the sign faces, or null if unknown
*/ */
public BlockFace getFacing() { public BlockFace getFacing() {
@ -96,17 +96,13 @@ public class RegionSign {
} }
/** /**
* Get the material of the sign. * Get the material of the sign as saved in the config.
* @return Material of the sign, normally {@link Material#WALL_SIGN} or {@link Material#SIGN_POST}, but could be something else or null. * @return Material of the sign, usually {@link Material#OAK_WALL_SIGN}, {@link Material#OAK_SIGN}, or one of the other wood types (different result for 1.13-), Material.AIR if none.
*/ */
public Material getMaterial() { public Material getMaterial() {
String name = getRegion().getConfig().getString("general.signs." + key + ".signType"); String name = getRegion().getConfig().getString("general.signs." + key + ".signType");
if ("WALL_SIGN".equals(name)) { Material result = Materials.signNameToMaterial(name);
return Materials.wallSign; return result == null ? Material.AIR : result;
} else if ("SIGN_POST".equals(name) || "SIGN".equals(name)) {
return Materials.floorSign;
}
return null;
} }
/** /**
@ -149,40 +145,34 @@ public class RegionSign {
} }
// Place the sign back (with proper rotation and type) after it has been hidden or (indirectly) destroyed // Place the sign back (with proper rotation and type) after it has been hidden or (indirectly) destroyed
Sign signState = null;
if(!Materials.isSign(block.getType())) { if(!Materials.isSign(block.getType())) {
Material signType = getMaterial(); Material signType = getMaterial();
block.setType(signType); // Don't do physics here, we first need to update the direction
block.setType(signType, false);
// This triggers a physics update, which pops the sign if not attached properly
if (!AreaShop.getInstance().getBukkitHandler().setSignFacing(block, getFacing())) {
AreaShop.warn("Failed to update the facing direction of the sign at", getStringLocation(), "to ", getFacing(), ", region:", getRegion().getName());
}
// Check if the sign has popped
if(!Materials.isSign(block.getType())) { if(!Materials.isSign(block.getType())) {
AreaShop.debug("Setting sign", key, "of region", getRegion().getName(), "failed, could not set sign block back"); AreaShop.warn("Setting sign", key, "of region", getRegion().getName(), "failed, could not set sign block back");
return false; return false;
} }
signState = (Sign) block.getState();
org.bukkit.material.Sign signData = (org.bukkit.material.Sign)signState.getData();
BlockFace signFace = getFacing();
if(signFace != null) {
signData.setFacingDirection(signFace);
signState.setData(signData);
}
}
if(signState == null) {
signState = (Sign) block.getState();
} }
// Save current rotation and type // Save current rotation and type
org.bukkit.material.Sign signData = (org.bukkit.material.Sign)signState.getData();
if(!regionConfig.isString("general.signs." + key + ".signType")) { if(!regionConfig.isString("general.signs." + key + ".signType")) {
String signType = signState.getType().name(); getRegion().setSetting("general.signs." + key + ".signType", block.getType().name());
if (signType.equals("SIGN")) {
signType = "SIGN_POST"; // Save with a backwards-compatible name
}
getRegion().setSetting("general.signs." + key + ".signType", signType);
} }
if(!regionConfig.isString("general.signs." + key + ".facing")) { if(!regionConfig.isString("general.signs." + key + ".facing")) {
getRegion().setSetting("general.signs." + key + ".facing", signData.getFacing().toString()); BlockFace signFacing = AreaShop.getInstance().getBukkitHandler().getSignFacing(block);
getRegion().setSetting("general.signs." + key + ".facing", signFacing == null ? null : signFacing.toString());
} }
// Apply replacements and color and then set it on the sign // Apply replacements and color and then set it on the sign
Sign signState = (Sign) block.getState();
for(int i = 0; i < signLines.length; i++) { for(int i = 0; i < signLines.length; i++) {
if(signLines[i] == null) { if(signLines[i] == null) {
signState.setLine(i, ""); signState.setLine(i, "");
@ -205,7 +195,12 @@ public class RegionSign {
if(signConfig == null || !signConfig.isSet(getRegion().getState().getValue().toLowerCase())) { if(signConfig == null || !signConfig.isSet(getRegion().getState().getValue().toLowerCase())) {
return false; return false;
} }
ConfigurationSection stateConfig = signConfig.getConfigurationSection(getRegion().getState().getValue().toLowerCase()); ConfigurationSection stateConfig = signConfig.getConfigurationSection(getRegion().getState().getValue().toLowerCase());
if(stateConfig == null) {
return false;
}
// Check the lines for the timeleft tag // Check the lines for the timeleft tag
for(int i = 1; i <= 4; i++) { for(int i = 1; i <= 4; i++) {
String line = stateConfig.getString("line" + i); String line = stateConfig.getString("line" + i);

View File

@ -28,7 +28,6 @@ import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.block.SignChangeEvent; import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.material.Sign;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -116,20 +115,19 @@ public class SignsFeature extends RegionFeature {
} }
// Check if still attached to a block // Check if still attached to a block
Block b = event.getBlock(); Block attachedBlock = plugin.getBukkitHandler().getSignAttachedTo(event.getBlock());
Sign s = (Sign) b.getState().getData(); // TODO: signs cannot be placed on all blocks, improve this check to isSolid()?
Block attachedBlock = b.getRelative(s.getAttachedFace());
if (attachedBlock.getType() != Material.AIR) { if (attachedBlock.getType() != Material.AIR) {
return; return;
} }
// Check if the rent sign is really the same as a saved rent // Check if the sign is really the same as a saved rent
RegionSign regionSign = SignsFeature.getSignByLocation(event.getBlock().getLocation()); RegionSign regionSign = SignsFeature.getSignByLocation(event.getBlock().getLocation());
if(regionSign == null) { if(regionSign == null) {
return; return;
} }
// Remove the sign so that it does not fall on the floor as an item (next region update will place it back) // Remove the sign so that it does not fall on the floor as an item (next region update will place it back when possible)
AreaShop.debug("onIndirectSignBreak: Removed block of sign for", regionSign.getRegion().getName(), "at", regionSign.getStringLocation()); AreaShop.debug("onIndirectSignBreak: Removed block of sign for", regionSign.getRegion().getName(), "at", regionSign.getStringLocation());
event.getBlock().setType(Material.AIR); event.getBlock().setType(Material.AIR);
event.setCancelled(true); event.setCancelled(true);
@ -138,34 +136,48 @@ public class SignsFeature extends RegionFeature {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onSignClick(PlayerInteractEvent event) { public void onSignClick(PlayerInteractEvent event) {
Block block = event.getClickedBlock(); Block block = event.getClickedBlock();
// Check for clicking a sign and rightclicking if (block == null) {
if((event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_BLOCK) return;
&& Materials.isSign(block.getType())) {
// Check if the rent sign is really the same as a saved rent
RegionSign regionSign = SignsFeature.getSignByLocation(block.getLocation());
if(regionSign == null) {
return;
}
Player player = event.getPlayer();
if(plugin.getSignlinkerManager().isInSignLinkMode(player)) {
return;
}
// Get the clicktype
GeneralRegion.ClickType clickType = null;
if(player.isSneaking() && event.getAction() == Action.LEFT_CLICK_BLOCK) {
clickType = GeneralRegion.ClickType.SHIFTLEFTCLICK;
} else if(!player.isSneaking() && event.getAction() == Action.LEFT_CLICK_BLOCK) {
clickType = GeneralRegion.ClickType.LEFTCLICK;
} else if(player.isSneaking() && event.getAction() == Action.RIGHT_CLICK_BLOCK) {
clickType = GeneralRegion.ClickType.SHIFTRIGHTCLICK;
} else if(!player.isSneaking() && event.getAction() == Action.RIGHT_CLICK_BLOCK) {
clickType = GeneralRegion.ClickType.RIGHTCLICK;
}
// Run the commands
boolean ran = regionSign.runSignCommands(player, clickType);
// Only cancel event if at least one command has been executed
event.setCancelled(ran);
} }
// Only listen to left and right clicks on blocks
if (!(event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_BLOCK)) {
return;
}
// Only care about clicking blocks
if(!Materials.isSign(block.getType())) {
return;
}
// Check if this sign belongs to a region
RegionSign regionSign = SignsFeature.getSignByLocation(block.getLocation());
if(regionSign == null) {
return;
}
// Ignore players that are in sign link mode (which will handle the event itself)
Player player = event.getPlayer();
if(plugin.getSignlinkerManager().isInSignLinkMode(player)) {
return;
}
// Get the clicktype
GeneralRegion.ClickType clickType = null;
if(player.isSneaking() && event.getAction() == Action.LEFT_CLICK_BLOCK) {
clickType = GeneralRegion.ClickType.SHIFTLEFTCLICK;
} else if(!player.isSneaking() && event.getAction() == Action.LEFT_CLICK_BLOCK) {
clickType = GeneralRegion.ClickType.LEFTCLICK;
} else if(player.isSneaking() && event.getAction() == Action.RIGHT_CLICK_BLOCK) {
clickType = GeneralRegion.ClickType.SHIFTRIGHTCLICK;
} else if(!player.isSneaking() && event.getAction() == Action.RIGHT_CLICK_BLOCK) {
clickType = GeneralRegion.ClickType.RIGHTCLICK;
}
boolean ran = regionSign.runSignCommands(player, clickType);
// Only cancel event if at least one command has been executed
event.setCancelled(ran);
} }
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
@ -278,8 +290,7 @@ public class SignsFeature extends RegionFeature {
if(durationSet) { if(durationSet) {
rent.setDuration(thirdLine); rent.setDuration(thirdLine);
} }
org.bukkit.material.Sign sign = (org.bukkit.material.Sign)event.getBlock().getState().getData(); rent.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), plugin.getBukkitHandler().getSignFacing(event.getBlock()), null);
rent.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), sign.getFacing(), null);
AddingRegionEvent addingRegionEvent = plugin.getFileManager().addRegion(rent); AddingRegionEvent addingRegionEvent = plugin.getFileManager().addRegion(rent);
if (addingRegionEvent.isCancelled()) { if (addingRegionEvent.isCancelled()) {
@ -383,8 +394,7 @@ public class SignsFeature extends RegionFeature {
if(priceSet) { if(priceSet) {
buy.setPrice(price); buy.setPrice(price);
} }
org.bukkit.material.Sign sign = (org.bukkit.material.Sign)event.getBlock().getState().getData(); buy.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), plugin.getBukkitHandler().getSignFacing(event.getBlock()), null);
buy.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), sign.getFacing(), null);
AddingRegionEvent addingRegionEvent = plugin.getFileManager().addRegion(buy); AddingRegionEvent addingRegionEvent = plugin.getFileManager().addRegion(buy);
if (addingRegionEvent.isCancelled()) { if (addingRegionEvent.isCancelled()) {
@ -428,12 +438,12 @@ public class SignsFeature extends RegionFeature {
} }
region = regions.get(0); region = regions.get(0);
} }
org.bukkit.material.Sign sign = (org.bukkit.material.Sign)event.getBlock().getState().getData();
if(thirdLine == null || thirdLine.isEmpty()) { if(thirdLine == null || thirdLine.isEmpty()) {
region.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), sign.getFacing(), null); region.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), plugin.getBukkitHandler().getSignFacing(event.getBlock()), null);
plugin.message(player, "addsign-success", region); plugin.message(player, "addsign-success", region);
} else { } else {
region.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), sign.getFacing(), thirdLine); region.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), plugin.getBukkitHandler().getSignFacing(event.getBlock()), thirdLine);
plugin.message(player, "addsign-successProfile", thirdLine, region); plugin.message(player, "addsign-successProfile", thirdLine, region);
} }

View File

@ -18,7 +18,6 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.Action; import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.material.Sign;
import org.bukkit.util.BlockIterator; import org.bukkit.util.BlockIterator;
import java.util.HashMap; import java.util.HashMap;
@ -131,8 +130,7 @@ public class SignLinkerManager extends Manager implements Listener {
plugin.message(player, "linksigns-alreadyRegistered", regionSign.getRegion()); plugin.message(player, "linksigns-alreadyRegistered", regionSign.getRegion());
return; return;
} }
Sign sign = (Sign)block.getState().getData(); linker.setSign(block.getLocation(), block.getType(), plugin.getBukkitHandler().getSignFacing(block));
linker.setSign(block.getLocation(), block.getType(), sign.getFacing());
} }
} }
} }

View File

@ -5,6 +5,7 @@ import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet;
import java.util.List; import java.util.List;
public class Materials { public class Materials {
@ -13,6 +14,35 @@ public class Materials {
} }
private static final HashSet<String> WALL_SIGN_TYPES = new HashSet<>(Arrays.asList(
// 1.14+ types
"ACACIA_WALL_SIGN",
"BIRCH_WALL_SIGN",
"DARK_OAK_WALL_SIGN",
"JUNGLE_WALL_SIGN",
"OAK_WALL_SIGN",
"SPRUCE_WALL_SIGN",
// Legacy types
"LEGACY_WALL_SIGN",
"WALL_SIGN"
));
private static final HashSet<String> FLOOR_SIGN_TYPES = new HashSet<>(Arrays.asList(
// 1.14+ types
"ACACIA_SIGN",
"BIRCH_SIGN",
"DARK_OAK_SIGN",
"JUNGLE_SIGN",
"OAK_SIGN",
"SPRUCE_SIGN",
// Legacy types
"LEGACY_SIGN",
"LEGACY_SIGN_POST",
"SIGN",
"SIGN_POST"
));
private static boolean legacyMaterials = false; private static boolean legacyMaterials = false;
static { static {
@ -29,34 +59,53 @@ public class Materials {
} }
} }
public static final Material wallSign = get("WALL_SIGN");
public static final Material floorSign = get("SIGN", "SIGN_POST");
/** /**
* Get Material version independent. * Get material based on a sign material name.
* @param name Name in 1.13 and later (uppercase, with underscores) * @param name Name of the sign material
* @return Material matching the name * @return null if not a sign, otherwise the material matching the name (when the material is not available on the current minecraft version, it returns the base type)
*/ */
public static Material get(String name) { public static Material signNameToMaterial(String name) {
return get(name, null); // Expected null case
} if (!isSign(name)) {
return null;
}
/** Material result = null;
* Get Material version independent. if (legacyMaterials) {
* @param name Name in 1.13 and later (uppercase, with underscores) // 1.12 and lower just know SIGN_POST, WALL_SIGN and SIGN
* @param legacyName Name in 1.12 and earlier (uppercase, with underscores) if (FLOOR_SIGN_TYPES.contains(name)) {
* @return Material matching the name result = Material.getMaterial("SIGN_POST");
*/ } else if (WALL_SIGN_TYPES.contains(name)) {
public static Material get(String name, String legacyName) { result = Material.getMaterial("WALL_SIGN");
Material result; if (result == null) {
if (legacyMaterials && legacyName != null) { result = Material.getMaterial("SIGN");
result = Material.getMaterial(legacyName); }
}
} else { } else {
// Try saved name (works for wood types on 1.14, regular types for below)
result = Material.getMaterial(name); result = Material.getMaterial(name);
if (result == null) {
// Cases for 1.13, which don't know wood types, but need new materials
if (FLOOR_SIGN_TYPES.contains(name)) {
// SIGN -> OAK_SIGN for 1.14
result = Material.getMaterial("OAK_SIGN");
// Fallback for 1.13
if (result == null) {
result = Material.getMaterial("SIGN");
}
} else if (WALL_SIGN_TYPES.contains(name)) {
// WALL_SIGN -> OAK_WALL_SIGN for 1.14
result = Material.getMaterial("OAK_WALL_SIGN");
// Fallback for 1.13
if (result == null) {
result = Material.getMaterial("WALL_SIGN");
}
}
}
} }
if (result == null) { if (result == null) {
AreaShop.debug("Materials.get() null result:", name, legacyName); AreaShop.debug("Materials.get() null result:", name, "legacyMaterials:", legacyMaterials);
} }
return result; return result;
@ -68,7 +117,16 @@ public class Materials {
* @return true if the given material is a sign * @return true if the given material is a sign
*/ */
public static boolean isSign(Material material) { public static boolean isSign(Material material) {
return material != null && material.name().contains("SIGN"); return isSign(material.name());
}
/**
* Check if a Material is a sign (of either the wall or floor type).
* @param name String to check
* @return true if the given material is a sign
*/
public static boolean isSign(String name) {
return name != null && (FLOOR_SIGN_TYPES.contains(name) || WALL_SIGN_TYPES.contains(name));
} }
} }

View File

@ -0,0 +1,33 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>areashop-bukkit-1_12</artifactId>
<packaging>jar</packaging>
<name>AreaShop Bukkit 1.7.9 until 1.12</name>
<version>latest</version>
<parent>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-parent</artifactId>
<version>parent</version>
</parent>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<scope>system</scope>
<version>any</version>
<systemPath>${project.basedir}/../dependencies/craftbukkit-1.7.9-R0.2-SNAPSHOT.jar</systemPath>
<type>jar</type>
<optional>true</optional>
</dependency>
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-interface</artifactId>
<version>latest</version>
<type>jar</type>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,76 @@
package me.wiefferink.areashop.handlers;
import me.wiefferink.areashop.interfaces.AreaShopInterface;
import me.wiefferink.areashop.interfaces.BukkitInterface;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.material.MaterialData;
public class BukkitHandler1_12 extends BukkitInterface {
public BukkitHandler1_12(AreaShopInterface pluginInterface) {
super(pluginInterface);
}
// Uses Sign, which is deprecated in 1.13+, broken in 1.14+
@Override
public BlockFace getSignFacing(Block block) {
if (block == null) {
return null;
}
BlockState blockState = block.getState();
if (blockState == null) {
return null;
}
MaterialData materialData = blockState.getData();
if(materialData instanceof org.bukkit.material.Sign) {
return ((org.bukkit.material.Sign)materialData).getFacing();
}
return null;
}
@Override
public boolean setSignFacing(Block block, BlockFace facing) {
if (block == null || facing == null) {
return false;
}
BlockState blockState = block.getState();
if (blockState == null) {
return false;
}
org.bukkit.material.Sign signData = (org.bukkit.material.Sign) blockState.getData();
if (signData == null) {
return false;
}
signData.setFacingDirection(facing);
blockState.setData(signData);
blockState.update(true, true);
return true;
}
@Override
public Block getSignAttachedTo(Block block) {
if (block == null) {
return null;
}
BlockState blockState = block.getState();
if (blockState == null) {
return null;
}
org.bukkit.material.Sign signData = (org.bukkit.material.Sign) blockState.getData();
if (signData == null) {
return null;
}
return block.getRelative(signData.getAttachedFace());
}
}

View File

@ -0,0 +1,31 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>areashop-bukkit-1_13</artifactId>
<packaging>jar</packaging>
<name>AreaShop Bukkit 1.13 and higher</name>
<version>latest</version>
<parent>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-parent</artifactId>
<version>parent</version>
</parent>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.13-R0.1-SNAPSHOT</version>
<type>jar</type>
<optional>true</optional>
</dependency>
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-interface</artifactId>
<version>latest</version>
<type>jar</type>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,97 @@
package me.wiefferink.areashop.handlers;
import me.wiefferink.areashop.interfaces.AreaShopInterface;
import me.wiefferink.areashop.interfaces.BukkitInterface;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Sign;
import org.bukkit.block.data.type.WallSign;
public class BukkitHandler1_13 extends BukkitInterface {
public BukkitHandler1_13(AreaShopInterface pluginInterface) {
super(pluginInterface);
}
// Uses BlockData, which does not yet exist in 1.12-
@Override
public BlockFace getSignFacing(Block block) {
if (block == null) {
return null;
}
BlockState blockState = block.getState();
if (blockState == null) {
return null;
}
BlockData blockData = blockState.getBlockData();
if (blockData == null) {
return null;
}
if(blockData instanceof WallSign) {
return ((WallSign) blockData).getFacing();
} else if(blockData instanceof Sign) {
return ((Sign) blockData).getRotation();
}
return null;
}
// Uses BlockData, WallSign and Sign which don't exist in 1.12-
@Override
public boolean setSignFacing(Block block, BlockFace facing) {
if (block == null || facing == null) {
return false;
}
BlockState blockState = block.getState();
if (blockState == null) {
return false;
}
BlockData blockData = blockState.getBlockData();
if (blockData == null) {
return false;
}
if(blockData instanceof WallSign) {
((WallSign) blockData).setFacing(facing);
} else if(blockData instanceof Sign) {
((Sign) blockData).setRotation(facing);
} else {
return false;
}
block.setBlockData(blockData);
return true;
}
@Override
public Block getSignAttachedTo(Block block) {
if (block == null) {
return null;
}
BlockState blockState = block.getState();
if (blockState == null) {
return null;
}
org.bukkit.block.data.BlockData blockData = blockState.getBlockData();
if (blockData == null) {
return null;
}
if(blockData instanceof WallSign) {
return block.getRelative(((WallSign) blockData).getFacing().getOppositeFace());
} else if(blockData instanceof Sign) {
return block.getRelative(BlockFace.DOWN);
}
return null;
}
}

View File

@ -1 +0,0 @@
/target

View File

@ -1 +0,0 @@
/target

View File

@ -0,0 +1,35 @@
package me.wiefferink.areashop.interfaces;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
public abstract class BukkitInterface {
protected final AreaShopInterface pluginInterface;
public BukkitInterface(AreaShopInterface pluginInterface) {
this.pluginInterface = pluginInterface;
}
/**
* Get the direciton a sign is facing.
* @param block Sign block to get the facing from
* @return direction the sign is facing
*/
public abstract BlockFace getSignFacing(Block block);
/**
* Set the direction a sign is facing.
* @param block Sign block to update
* @param facing direction to let the sign face
* @return true when successful, otherwise false
*/
public abstract boolean setSignFacing(Block block, BlockFace facing);
/**
* Get the block a sign is attached to.
* @param block Sign block
* @return Block the sign is attached to, or null when not a sign or not attached
*/
public abstract Block getSignAttachedTo(Block block);
}

View File

@ -11,12 +11,30 @@ public abstract class WorldEditInterface {
this.pluginInterface = pluginInterface; this.pluginInterface = pluginInterface;
} }
// Different way to restore blocks per implementation, newer ones support entities as well /**
* Different way to restore blocks per implementation, newer ones support entities as well.
* Why: the schematic api has changed between WorldEdit 5 and 6, and the schematic format changed between 6 and 7
* @param file File to try restoring from to the location of the region
* @param regionInterface Region to restore from
* @return true when successful, otherwise false
*/
public abstract boolean restoreRegionBlocks(File file, GeneralRegionInterface regionInterface); public abstract boolean restoreRegionBlocks(File file, GeneralRegionInterface regionInterface);
// Different way to save blocks per implementation, newer ones support entities as well /**
* Different way to save blocks per implementation, newer ones support entities as well.
* Why: the schematic api has changed between WorldEdit 5 and 6, and the schematic format changed between 6 and 7
* @param file File to try saving the region to
* @param regionInterface Region to restore from
* @return true when successful, otherwise false
*/
public abstract boolean saveRegionBlocks(File file, GeneralRegionInterface regionInterface); public abstract boolean saveRegionBlocks(File file, GeneralRegionInterface regionInterface);
/**
* Get the selection of the player.
* Why: the underlying WorldEdit selection class has changed from interface <-> class
* @param player Player to get the selection for
* @return WorldEditSelection if the player has selected something, otherwise null
*/
public abstract WorldEditSelection getPlayerSelection(Player player); public abstract WorldEditSelection getPlayerSelection(Player player);
} }

View File

@ -1 +0,0 @@
/target

View File

@ -1 +0,0 @@
/target

View File

@ -1 +0,0 @@
/target

View File

@ -1 +0,0 @@
/target

View File

@ -1 +0,0 @@
/target

View File

@ -1 +0,0 @@
/target

View File

@ -1 +0,0 @@
/target

View File

@ -1 +0,0 @@
/target

View File

@ -1 +0,0 @@
/target

View File

@ -50,6 +50,8 @@
<modules> <modules>
<module>areashop-interface</module> <module>areashop-interface</module>
<module>areashop-bukkit-1_12</module>
<module>areashop-bukkit-1_13</module>
<module>areashop-worldguard-5</module> <module>areashop-worldguard-5</module>
<module>areashop-worldguard-6</module> <module>areashop-worldguard-6</module>
<module>areashop-worldguard-6_1_3</module> <module>areashop-worldguard-6_1_3</module>