Allow specifying of valid player names (#410)

This allows plugins which allow differently named players to work e.g. Floodgate. (Fixes #383)

Co-authored-by: Phoenix616 <max@themoep.de>
This commit is contained in:
Daniel B 2021-03-17 22:46:05 +01:00 committed by GitHub
parent e6b05ff982
commit f68a3203ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 5 deletions

View File

@ -197,6 +197,9 @@ public class Properties {
@ConfigurationComment("This makes sure that the UUIDs of player shop accounts match the server's online-mode setting. Disabling this might lead to issues with offline players and is therefore unsupported!")
public static boolean ENSURE_CORRECT_PLAYERID = true;
@ConfigurationComment("This regexp validates the name of the player. If the name doesn't match, the player will neither be able to create a valid shop sign, nor buy/sell from a shop. Note to Bedrock players: If you have Floodgate on your server, you should set this regexp to ^\\\\*?\\\\w+$ and ENSURE_CORRECT_PLAYERID to false")
public static String VALID_PLAYERNAME_REGEXP = "^\\\\w+$";
@PrecededBySpace
@ConfigurationComment("Should we block shops that sell things for more than they buy? (This prevents newbies from creating shops that would be exploited)")
public static boolean BLOCK_SHOPS_WITH_SELL_PRICE_HIGHER_THAN_BUY_PRICE = true;

View File

@ -1,5 +1,6 @@
package com.Acrobot.ChestShop.Listeners.PreTransaction;
import com.Acrobot.ChestShop.Configuration.Properties;
import com.Acrobot.ChestShop.Events.PreTransactionEvent;
import com.Acrobot.ChestShop.Signs.ChestShopSign;
import org.bukkit.event.EventHandler;
@ -10,14 +11,13 @@ import java.util.regex.Pattern;
public class InvalidNameIgnorer implements Listener {
private final static Pattern USERNAME_PATTERN = Pattern.compile("^\\w+$");
@EventHandler(priority = EventPriority.LOWEST)
public static void onPreTransaction(PreTransactionEvent event) {
if (event.isCancelled()) {
return;
}
Pattern USERNAME_PATTERN = Pattern.compile(Properties.VALID_PLAYERNAME_REGEXP);
String name = event.getClient().getName();
if (ChestShopSign.isAdminShop(name) || !USERNAME_PATTERN.matcher(name).matches()) {
event.setCancelled(PreTransactionEvent.TransactionOutcome.INVALID_CLIENT_NAME);

View File

@ -34,7 +34,6 @@ public class ChestShopSign {
public static final byte ITEM_LINE = 3;
public static final Pattern[][] SHOP_SIGN_PATTERN = {
{ Pattern.compile("^?[\\w \\-.:]*$") },
{ Pattern.compile("^[1-9][0-9]{0,5}$"), Pattern.compile("^Q [1-9][0-9]{0,4} : C [0-9]{0,5}$") },
{
Pattern.compile("(?i)^((\\d*([.e]\\d+)?)|free)$"),
@ -150,10 +149,33 @@ public class ChestShopSign {
}
public static boolean isValidPreparedSign(String[] lines) {
for (int i = 0; i < 4; i++) {
// The first line is the name of the shop owner
String playername = lines[0];
// If the shop owner is not blank (auto-filled) or the admin shop string, we need to validate it
if ((!isAdminShop(playername)) && (playername.length() > 0)) {
// Prepare regexp patterns
Pattern playernamePattern = Pattern.compile(Properties.VALID_PLAYERNAME_REGEXP); // regexp from config file
Pattern playernameWithIdPattern = Pattern.compile(":[A-Za-z0-9]+$"); // regexp to match ':' and a base62 encoded string
// Check if the playername has an ID. This can happen on duplicate or too long names
if (playernameWithIdPattern.matcher(playername).matches()) {
// Playername matches the id pattern, so validate everything before the last ':'
playername = playername.substring(0, playername.lastIndexOf(":") - 1);
}
// If the playername doesn't match, this is not a valid sign, so return
if (!playernamePattern.matcher(playername).matches()) {
return false;
}
}
// The first line is valid. Now validate the last 3 lines against the predefined regexp patterns.
for (int i = 0; i < 3; i++) {
boolean matches = false;
for (Pattern pattern : SHOP_SIGN_PATTERN[i]) {
if (pattern.matcher(lines[i]).matches()) {
if (pattern.matcher(lines[i+1]).matches()) {
matches = true;
break;
}
@ -162,6 +184,8 @@ public class ChestShopSign {
return false;
}
}
// All lines are looking good. If the price line contains only one ':', then this is a valid prepared sign.
return lines[PRICE_LINE].indexOf(':') == lines[PRICE_LINE].lastIndexOf(':');
}
}