This commit is contained in:
Telesphoreo 2020-11-08 13:20:58 -06:00
commit 7b3a4babd1
34 changed files with 389 additions and 1451 deletions

62
pom.xml
View File

@ -5,7 +5,7 @@
<groupId>me.totalfreedom</groupId>
<artifactId>TotalFreedomMod</artifactId>
<version>2020.10</version>
<version>2020.11</version>
<packaging>jar</packaging>
<properties>
@ -114,20 +114,25 @@
<id>ess-repo</id>
<url>https://ci.ender.zone/plugin/repository/everything/</url>
</repository>
<repository>
<id>telesphoreo-repo</id>
<url>https://telesphoreo.me/repo/maven/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.7</version>
<version>2.8.0</version>
<scope>compile</scope>
</dependency>
@ -141,35 +146,49 @@
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.14</version>
<version>1.15</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.telesphoreo</groupId>
<artifactId>mojangson</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>1.7</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.16.2-R0.1-SNAPSHOT</version>
<version>1.16.3-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.TotalFreedom</groupId>
<groupId>com.github.TotalFreedomMC</groupId>
<artifactId>BukkitTelnet</artifactId>
<version>4.5-pre1</version>
<version>541e9fdb84</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.TFPatches</groupId>
<groupId>com.github.TotalFreedomMC</groupId>
<artifactId>TF-LibsDisguises</artifactId>
<version>0cfa32159a</version>
<version>48f01cf2fe</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<version>7.1.0</version>
<version>7.2.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@ -197,7 +216,7 @@
<dependency>
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-bukkit</artifactId>
<version>7.0.3</version>
<version>7.0.4</version>
<scope>provided</scope>
</dependency>
@ -232,19 +251,21 @@
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.11</version>
<version>0.9.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javassist</groupId>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
<version>3.27.0-GA</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.github.TFPatches</groupId>
<groupId>com.github.TotalFreedomMC</groupId>
<artifactId>TFGuilds</artifactId>
<version>ad93b9ed00</version>
<version>db036fb187</version>
<scope>provided</scope>
</dependency>
@ -252,6 +273,7 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
@ -419,6 +441,10 @@
<pattern>io.papermc.lib</pattern>
<shadedPattern>me.totalfreedom.totalfreedommod.paperlib</shadedPattern> <!-- Replace this -->
</relocation>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>me.totalfreedom.totalfreedommod</shadedPattern>
</relocation>
</relocations>
<artifactSet>
<includes>
@ -426,9 +452,11 @@
<include>org.apache.commons:commons-lang3</include>
<include>commons-codec:commons-codec</include>
<include>org.reflections:reflections</include>
<include>javassist:javassist</include>
<include>org.javassist:javassist</include>
<include>me.rayzr522:jsonmessage</include>
<include>io.papermc:paperlib</include>
<include>me.telesphoreo:mojangson</include>
<include>org.bstats:bstats-bukkit</include>
</includes>
</artifactSet>
</configuration>

View File

@ -1,23 +0,0 @@
package ca.momothereal.mojangson;
import ca.momothereal.mojangson.ex.MojangsonParseException;
import ca.momothereal.mojangson.value.MojangsonString;
import ca.momothereal.mojangson.value.MojangsonValue;
public class MojangsonFinder
{
/**
* Automatically detects the appropriate MojangsonValue from the given value.
*
* @param value The value to parse
* @return The resulting MojangsonValue. If the type couldn't be found, it falls back to MojangsonString
* @throws MojangsonParseException if the given value could not be parsed
*/
public static MojangsonValue readFromValue(String value) throws MojangsonParseException
{
MojangsonValue val = new MojangsonString();
val.read(value);
return val;
}
}

View File

@ -1,53 +0,0 @@
package ca.momothereal.mojangson;
public enum MojangsonToken
{
COMPOUND_START(0, "Compound_Start", '{'),
COMPOUND_END(1, "Compound_End", '}'),
ELEMENT_SEPERATOR(2, "Element_Seperator", ','),
ARRAY_START(3, "Array_Start", '['),
ARRAY_END(4, "Array_End", ']'),
ELEMENT_PAIR_SEPERATOR(5, "Pair_Seperator", ':'),
STRING_QUOTES(6, "String_Quotes", '\"'),
DOUBLE_SUFFIX(8, "Double_Suffix", 'd'),
BYTE_SUFFIX(9, "Byte_Suffix", 'b'),
FLOAT_SUFFIX(10, "Float_Suffix", 'f'),
SHORT_SUFFIX(11, "Short_Suffix", 's'),
LONG_SUFFIX(12, "Long_Suffix", 'l'),
WHITE_SPACE(13, "WhiteSpace", ' ');
private int id;
private String name;
private char symbol;
MojangsonToken(int id, String name, char symbol)
{
this.id = id;
this.name = name;
this.symbol = symbol;
}
public int getId()
{
return id;
}
public String getName()
{
return name;
}
public char getSymbol()
{
return symbol;
}
@Override
public String toString()
{
return String.valueOf(symbol);
}
}

View File

@ -1,42 +0,0 @@
package ca.momothereal.mojangson.ex;
public class MojangsonParseException extends Exception
{
private ParseExceptionReason reason;
public MojangsonParseException(String message, ParseExceptionReason reason)
{
super(message);
this.reason = reason;
}
public ParseExceptionReason getReason()
{
return reason;
}
@Override
public String getMessage()
{
return reason.getMessage() + ": " + super.getMessage();
}
public enum ParseExceptionReason
{
INVALID_FORMAT_NUM("Given value is not numerical"),
UNEXPECTED_SYMBOL("Unexpected symbol in Mojangson string");
private String message;
ParseExceptionReason(String message)
{
this.message = message;
}
public String getMessage()
{
return message;
}
}
}

View File

@ -1,144 +0,0 @@
package ca.momothereal.mojangson.value;
import ca.momothereal.mojangson.MojangsonFinder;
import ca.momothereal.mojangson.ex.MojangsonParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static ca.momothereal.mojangson.MojangsonToken.*;
public class MojangsonCompound extends HashMap<String, List<MojangsonValue>> implements MojangsonValue<Map<String, MojangsonValue>>
{
private final int C_COMPOUND_START = 0; // Parsing context
private final int C_COMPOUND_PAIR_KEY = 1; // Parsing context
private final int C_COMPOUND_PAIR_VALUE = 2; // Parsing context
public MojangsonCompound()
{
}
public MojangsonCompound(Map map)
{
super(map);
}
@Override
public void write(StringBuilder builder)
{
builder.append(COMPOUND_START);
boolean start = true;
for (String key : keySet())
{
if (start)
{
start = false;
}
else
{
builder.append(ELEMENT_SEPERATOR);
}
builder.append(key).append(ELEMENT_PAIR_SEPERATOR);
List<MojangsonValue> value = get(key);
for (MojangsonValue val : value)
{
val.write(builder);
}
}
builder.append(COMPOUND_END);
}
@Override
public void read(String string) throws MojangsonParseException
{
int context = C_COMPOUND_START;
String tmp_key = "", tmp_val = "";
int scope = 0;
boolean inString = false;
for (int index = 0; index < string.length(); index++)
{
Character character = string.charAt(index);
if (character == STRING_QUOTES.getSymbol())
{
inString = !inString;
}
if (character == WHITE_SPACE.getSymbol())
{
if (!inString)
{
continue;
}
}
if ((character == COMPOUND_START.getSymbol() || character == ARRAY_START.getSymbol()) && !inString)
{
scope++;
}
if ((character == COMPOUND_END.getSymbol() || character == ARRAY_END.getSymbol()) && !inString)
{
scope--;
}
if (context == C_COMPOUND_START)
{
if (character != COMPOUND_START.getSymbol())
{
parseException(index, character);
return;
}
context++;
continue;
}
if (context == C_COMPOUND_PAIR_KEY)
{
if (character == ELEMENT_PAIR_SEPERATOR.getSymbol() && scope <= 1)
{
context++;
continue;
}
tmp_key += character;
continue;
}
if (context == C_COMPOUND_PAIR_VALUE)
{
if ((character == ELEMENT_SEPERATOR.getSymbol() || character == COMPOUND_END.getSymbol()) && scope <= 1 && !inString)
{
context = C_COMPOUND_PAIR_KEY;
computeIfAbsent(tmp_key, k -> new ArrayList<>()).add(MojangsonFinder.readFromValue(tmp_val));
tmp_key = tmp_val = "";
continue;
}
tmp_val += character;
}
}
}
@Override
public Map<String, MojangsonValue> getValue()
{
HashMap<String, MojangsonValue> hack = new HashMap<>();
for (String string : keySet())
{
for (MojangsonValue value : get(string))
{
hack.put(string, value);
}
}
return hack;
}
@Override
public Class getValueClass()
{
return Map.class;
}
private void parseException(int index, char symbol) throws MojangsonParseException
{
throw new MojangsonParseException("Index: " + index + ", symbol: \'" + symbol + "\'", MojangsonParseException.ParseExceptionReason.UNEXPECTED_SYMBOL);
}
}

View File

@ -1,57 +0,0 @@
package ca.momothereal.mojangson.value;
import ca.momothereal.mojangson.MojangsonToken;
import ca.momothereal.mojangson.ex.MojangsonParseException;
public class MojangsonString implements MojangsonValue<String>
{
private String value;
public MojangsonString()
{
}
public MojangsonString(String value)
{
this.value = value;
}
public String getValue()
{
return value;
}
public void setValue(String value)
{
this.value = value;
}
@Override
public void write(StringBuilder builder)
{
builder.append(MojangsonToken.STRING_QUOTES).append(value).append(MojangsonToken.STRING_QUOTES);
}
@Override
public Class getValueClass()
{
return String.class;
}
@Override
public void read(String string) throws MojangsonParseException
{
Character lastChar = string.charAt(string.length() - 1);
Character firstChar = string.charAt(0);
if (firstChar == MojangsonToken.STRING_QUOTES.getSymbol() && lastChar == MojangsonToken.STRING_QUOTES.getSymbol())
{
value = string.substring(1, string.length() - 1);
}
else
{
value = string;
}
}
}

View File

@ -1,42 +0,0 @@
package ca.momothereal.mojangson.value;
import ca.momothereal.mojangson.ex.MojangsonParseException;
/**
* Represents a value inside a compound or array.
*
* @param <T> The type of value this MojangsonValue holds
*/
public interface MojangsonValue<T>
{
/**
* Writes the value to a StringBuilder buffer.
*
* @param builder The buffer to write to
*/
void write(StringBuilder builder);
/**
* Parses and updates the current value to the given string representation
*
* @param string The string representation of the value
* @throws MojangsonParseException if the given value cannot be parsed
*/
void read(String string) throws MojangsonParseException;
/**
* Gets the current literal value
*
* @return The current literal value of the MojangsonValue
*/
T getValue();
/**
* Gets the literal value's class
*
* @return The literal value's class
*/
Class getValueClass();
}

View File

@ -50,7 +50,7 @@ import me.totalfreedom.totalfreedommod.util.MethodTimer;
import me.totalfreedom.totalfreedommod.world.CleanroomChunkGenerator;
import me.totalfreedom.totalfreedommod.world.WorldManager;
import me.totalfreedom.totalfreedommod.world.WorldRestrictions;
import org.bstats.Metrics;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.Plugin;

View File

@ -7,6 +7,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
@ -103,7 +104,7 @@ public class CoreProtectBridge extends FreedomService
@Override
public void run()
{
coreProtect.performRollback(86400, Arrays.asList(name), null, null, null, null, 0, null);
coreProtect.performRollback(86400, Collections.singletonList(name), null, null, null, null, 0, null);
}
}.runTaskAsynchronously(plugin);
}
@ -123,7 +124,7 @@ public class CoreProtectBridge extends FreedomService
@Override
public void run()
{
coreProtect.performRestore(86400, Arrays.asList(name), null, null, null, null, 0, null);
coreProtect.performRestore(86400, Collections.singletonList(name), null, null, null, null, 0, null);
}
}.runTaskAsynchronously(plugin);
}

View File

@ -14,7 +14,6 @@ import java.util.Map;
import me.totalfreedom.totalfreedommod.FreedomService;
import net.coreprotect.CoreProtect;
import net.coreprotect.CoreProtectAPI;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
@ -24,7 +23,7 @@ import org.bukkit.block.data.BlockData;
public class FAWEBridge extends FreedomService
{
private CoreProtectAPI api;
private final CoreProtectAPI api = plugin.cpb.getCoreProtectAPI();;
private World world = null;
private final Map<Map.Entry<String, EditSession>, Map<BlockVector3, String>> blocksBroken = new HashMap<>();
private final Map<Map.Entry<String, EditSession>, Map.Entry<Pattern, List<BlockVector3>>> blocksPlaced = new HashMap<>();
@ -32,68 +31,62 @@ public class FAWEBridge extends FreedomService
@Override
public void onStart()
{
api = ((CoreProtect)Bukkit.getPluginManager().getPlugin("CoreProtect")).getAPI();
/*
* Iterates over blocks placed by GenerationCommands (in the EditSession) and adds them to the CoreProtect logs.
*/
server.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable()
server.getScheduler().scheduleSyncRepeatingTask(plugin, () ->
{
@Override
public void run()
if (!(blocksBroken.isEmpty() && blocksPlaced.isEmpty()))
{
if (!(blocksBroken.isEmpty() && blocksPlaced.isEmpty()))
// Send all broken blocks from the last ticks to the CoreProtect API.
Map.Entry<String, EditSession> playerAndSessionEntry = null;
for (Map.Entry<Map.Entry<String, EditSession>, Map<BlockVector3, String>> entry : blocksBroken.entrySet())
{
// Send all broken blocks from the last ticks to the CoreProtect API.
Map.Entry<String, EditSession> playerAndSessionEntry = null;
for (Map.Entry<Map.Entry<String, EditSession>, Map<BlockVector3, String>> entry : blocksBroken.entrySet())
{
playerAndSessionEntry = entry.getKey();
Map<BlockVector3, String> dataAndVectorEntry = entry.getValue();
List<BlockVector3> blockVector3List = new ArrayList<>();
blockVector3List.addAll(dataAndVectorEntry.keySet()); // Deep clone the block vector to avoid a change later in the code.
playerAndSessionEntry = entry.getKey();
Map<BlockVector3, String> dataAndVectorEntry = entry.getValue();
List<BlockVector3> blockVector3List = new ArrayList<>();
blockVector3List.addAll(dataAndVectorEntry.keySet()); // Deep clone the block vector to avoid a change later in the code.
for (BlockVector3 blockVector3 : blockVector3List)
for (BlockVector3 blockVector3 : blockVector3List)
{
if (blockVector3 != null)
{
if (blockVector3 != null)
{
EditSession editSession = playerAndSessionEntry.getValue();
World world = server.getWorld(editSession.getWorld().getName());
Location location = new Location(world, blockVector3.getX(), blockVector3.getY(), blockVector3.getZ());
BlockData blockData = server.createBlockData(dataAndVectorEntry.get(blockVector3));
api.logRemoval(playerAndSessionEntry.getKey(), location, blockData.getMaterial(), blockData);
}
EditSession editSession = playerAndSessionEntry.getValue();
World world = server.getWorld(editSession.getWorld().getName());
Location location = new Location(world, blockVector3.getX(), blockVector3.getY(), blockVector3.getZ());
BlockData blockData = server.createBlockData(dataAndVectorEntry.get(blockVector3));
api.logRemoval(playerAndSessionEntry.getKey(), location, blockData.getMaterial(), blockData);
}
}
// Clear after broken blocks have been updated.
blocksBroken.values().clear();
blocksBroken.putIfAbsent(playerAndSessionEntry, new HashMap<>());
// Send all blocks placed to the CoreProtect API (except from the air as it's only a broken block).
for (Map.Entry<Map.Entry<String, EditSession>, Map.Entry<Pattern, List<BlockVector3>>> entry : blocksPlaced.entrySet())
{
playerAndSessionEntry = entry.getKey();
Map.Entry<Pattern, List<BlockVector3>> patternAndListEntry = entry.getValue();
Pattern pattern = patternAndListEntry.getKey();
List<BlockVector3> blockVector3List = new ArrayList<>();
blockVector3List.addAll(patternAndListEntry.getValue()); // Deep clone the block vector to avoid a change later in the code.
for (BlockVector3 blockVector3 : blockVector3List)
{
if (blockVector3 != null && !pattern.apply(blockVector3).getBlockType().getMaterial().isAir())
{
World world = server.getWorld(playerAndSessionEntry.getValue().getWorld().getName());
Location location = new Location(world, blockVector3.getX(), blockVector3.getY(), blockVector3.getZ());
BaseBlock block = pattern.apply(blockVector3);
Material material = Material.getMaterial(block.getBlockType().getId().replaceFirst("minecraft:", "").toUpperCase());
api.logPlacement(playerAndSessionEntry.getKey(), location, material, material.createBlockData());
}
}
}
blocksPlaced.values().forEach(collection -> collection.getValue().clear());
}
// Clear after broken blocks have been updated.
blocksBroken.values().clear();
blocksBroken.putIfAbsent(playerAndSessionEntry, new HashMap<>());
// Send all blocks placed to the CoreProtect API (except from the air as it's only a broken block).
for (Map.Entry<Map.Entry<String, EditSession>, Map.Entry<Pattern, List<BlockVector3>>> entry : blocksPlaced.entrySet())
{
playerAndSessionEntry = entry.getKey();
Map.Entry<Pattern, List<BlockVector3>> patternAndListEntry = entry.getValue();
Pattern pattern = patternAndListEntry.getKey();
List<BlockVector3> blockVector3List = new ArrayList<>();
blockVector3List.addAll(patternAndListEntry.getValue()); // Deep clone the block vector to avoid a change later in the code.
for (BlockVector3 blockVector3 : blockVector3List)
{
if (blockVector3 != null && !pattern.apply(blockVector3).getBlockType().getMaterial().isAir())
{
World world = server.getWorld(playerAndSessionEntry.getValue().getWorld().getName());
Location location = new Location(world, blockVector3.getX(), blockVector3.getY(), blockVector3.getZ());
BaseBlock block = pattern.apply(blockVector3);
Material material = Material.getMaterial(block.getBlockType().getId().replaceFirst("minecraft:", "").toUpperCase());
api.logPlacement(playerAndSessionEntry.getKey(), location, material, material.createBlockData());
}
}
}
blocksPlaced.values().forEach(collection -> collection.getValue().clear());
}
}, 0L, 40L);
}
@ -101,10 +94,8 @@ public class FAWEBridge extends FreedomService
@Override
public void onStop()
{
}
public void logBlockEdit(String playerName, EditSession editSession, Pattern pattern, BlockVector3 blockVector3)
{
// Cache the world used for the next iterations to come.

View File

@ -60,7 +60,7 @@ public class WorldEditBridge extends FreedomService
{
for (int i = 0; i < count; i++)
{
com.sk89q.worldedit.entity.Player fuckyou = (com.sk89q.worldedit.entity.Player)bukkitPlayer;
com.sk89q.worldedit.entity.Player fuckyou = bukkitPlayer;
session.undo(session.getBlockBag(fuckyou), fuckyou);
}
}

View File

@ -13,7 +13,6 @@ import org.bukkit.entity.Player;
@CommandParameters(description = "Shows the amount of coins you have or another player has", usage = "/<command> [playername]")
public class Command_coins extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{

View File

@ -0,0 +1,52 @@
package me.totalfreedom.totalfreedommod.command;
import me.totalfreedom.totalfreedommod.player.PlayerData;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.shop.ShopItem;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.OP, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Change your login message", usage = "/<command> [message]")
public class Command_loginmessage extends FreedomCommand
{
@Override
public boolean run(final CommandSender sender, final Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (!plugin.pl.getData(playerSender).hasItem(ShopItem.LOGIN_MESSAGES) && !isStaff(playerSender))
{
msg("You did not purchase the ability to use login messages! Purchase the ability from the shop.", ChatColor.RED);
return true;
}
if (args.length == 0)
{
playerSender.openInventory(plugin.sh.generateLoginMessageGUI(playerSender));
return true;
}
checkRank(Rank.ADMIN);
String message = StringUtils.join(args, " ");
if (!message.contains("%rank%") && !message.contains("%coloredrank%"))
{
msg("Your login message must contain your rank. Use either %rank% or %coloredrank% to specify where you want the rank", ChatColor.RED);
return true;
}
int length = message.replace("%name%", "").replace("%rank%", "").replace("%coloredrank%", "").replace("%art%", "").length();
if (length > 100)
{
msg("Your login message cannot be more than 100 characters (excluding your rank and your name)", ChatColor.RED);
return true;
}
PlayerData data = getData(playerSender);
data.setLoginMessage(message);
plugin.pl.save(data);
msg("Your login message is now the following:\n" + plugin.rm.craftLoginMessage(playerSender, message), ChatColor.GREEN);
return true;
}
}

View File

@ -88,7 +88,7 @@ public class Command_manageshop extends FreedomCommand
msg(PLAYER_NOT_FOUND);
return true;
}
playerData.setCoins(playerData.getCoins() + amount);
playerData.setCoins(playerData.getCoins() - amount);
if (playerData.getCoins() < 0)
{
playerData.setCoins(0);

View File

@ -17,7 +17,7 @@ import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.ADMIN, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Manage your staff entry.", usage = "/<command> [-o <staff member>] <clearips | clearip <ip> | setlogin <message> | clearlogin | setscformat <format> | clearscformat> | oldtags | logstick | syncroles>")
public class Command_mystaff extends FreedomCommand
public class Command_myadmin extends FreedomCommand
{
@Override
@ -139,46 +139,6 @@ public class Command_mystaff extends FreedomCommand
return true;
}
case "setlogin":
{
checkRank(Rank.ADMIN);
if (args.length < 2)
{
return false;
}
String message = StringUtils.join(args, " ", 1, args.length);
if (!message.contains("%rank%") && !message.contains("%coloredrank%"))
{
msg("Your login message must contain your rank. Use either %rank% or %coloredrank% to specify where you want the rank", ChatColor.RED);
return true;
}
int length = message.replace("%name%", "").replace("%rank%", "").replace("%coloredrank%", "").length();
if (length > 100)
{
msg("Your login message cannot be more than 100 characters (excluding your rank and your name)", ChatColor.RED);
return true;
}
FUtil.staffAction(sender.getName(), "Setting personal login message" + (init == null ? "" : " for " + targetPlayer.getName()), false);
target.setLoginMessage(message);
String previewMessage = plugin.rm.craftLoginMessage(targetPlayer, message);
msg((init == null ? "Your" : targetPlayer.getName() + "'s") + " login message is now: ");
msg("> " + previewMessage);
plugin.sl.save(target);
plugin.sl.updateTables();
return true;
}
case "clearlogin":
{
checkRank(Rank.ADMIN);
FUtil.staffAction(sender.getName(), "Clearing personal login message" + (init == null ? "" : " for " + targetPlayer.getName()), false);
target.setLoginMessage(null);
plugin.sl.save(target);
plugin.sl.updateTables();
return true;
}
case "setscformat":
{
String format = StringUtils.join(args, " ", 1, args.length);
@ -229,10 +189,6 @@ public class Command_mystaff extends FreedomCommand
return true;
}
case "genbackupcodes":
msg("Moved to /pv genbackupcodes", ChatColor.RED);
return true;
default:
{
return false;
@ -248,8 +204,8 @@ public class Command_mystaff extends FreedomCommand
return Collections.emptyList();
}
List<String> singleArguments = Arrays.asList("clearips", "setlogin", "setscformat");
List<String> doubleArguments = Arrays.asList("clearip", "clearlogin", "clearscformat", "oldtags", "syncroles");
List<String> singleArguments = Arrays.asList("clearips", "setscformat");
List<String> doubleArguments = Arrays.asList("clearip", "clearscformat", "syncroles");
if (args.length == 1)
{
List<String> options = new ArrayList<>();

View File

@ -3,7 +3,6 @@ package me.totalfreedom.totalfreedommod.command;
import io.papermc.lib.PaperLib;
import java.util.HashMap;
import java.util.Map;
import java.util.TimerTask;
import me.totalfreedom.totalfreedommod.player.FPlayer;
import me.totalfreedom.totalfreedommod.player.PlayerData;
import me.totalfreedom.totalfreedommod.rank.Rank;
@ -12,6 +11,7 @@ import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
@CommandPermissions(level = Rank.OP, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Ride on the top of the specified player.", usage = "/<command> <playername | mode <normal | off | ask>>")
@ -39,7 +39,7 @@ public class Command_ride extends FreedomCommand
{
if (!RIDE_REQUESTS.containsKey(playerSender))
{
msg("You don't have a request currently.");
msg("You don't have any pending requests.");
return true;
}
@ -59,6 +59,7 @@ public class Command_ride extends FreedomCommand
PaperLib.teleportAsync(requester, playerSender.getLocation());
}
RIDE_REQUESTS.remove(playerSender);
playerSender.addPassenger(requester);
return true;
}
@ -67,7 +68,7 @@ public class Command_ride extends FreedomCommand
{
if (!RIDE_REQUESTS.containsKey(playerSender))
{
msg("You don't have a request currently.");
msg("You don't have any pending requests.");
return true;
}
Player requester = RIDE_REQUESTS.get(playerSender);
@ -125,22 +126,23 @@ public class Command_ride extends FreedomCommand
player.sendMessage(ChatColor.AQUA + sender.getName() + " has requested to ride you.");
player.sendMessage(ChatColor.AQUA + "Type " + ChatColor.GREEN + "/ride accept" + ChatColor.AQUA + " to allow the player to ride you.");
player.sendMessage(ChatColor.AQUA + "Type " + ChatColor.RED + "/ride deny" + ChatColor.AQUA + " to deny the player permission.");
player.sendMessage(ChatColor.AQUA + "Request will expire after 30 seconds.");
player.sendMessage(ChatColor.AQUA + "Request will expire in 30 seconds.");
RIDE_REQUESTS.put(player, playerSender);
timer.schedule(new TimerTask()
new BukkitRunnable()
{
@Override
public void run()
{
if (!RIDE_REQUESTS.containsKey(player))
{
return;
}
RIDE_REQUESTS.remove(player);
msg("Request expired.", ChatColor.RED);
playerSender.sendMessage(ChatColor.RED + "It has been 30 seconds and " + player.getName() + " has not accepted your request.");
player.sendMessage(ChatColor.RED + "Request expired.");
}
}, 30000);
}.runTaskLater(plugin, 20 * 30);
return true;
}

View File

@ -99,11 +99,6 @@ public enum ConfigEntry
PTERO_ADMIN_KEY(String.class, "ptero.admin_key"),
PTERO_SERVER_KEY(String.class, "ptero.server_key"),
//
DONATION_PROBOARDS_URL(String.class, "donation.proboards_url"),
DONATION_GROUP_ID(String.class, "donation.donator_group_id"),
DONATION_SESSION_ID(String.class, "donation.session_id"),
DONATION_CSRF_TOKEN(String.class, "donation.csrf_token"),
//
SHOP_ENABLED(Boolean.class, "shop.enabled"),
SHOP_TITLE(String.class, "shop.title"),
SHOP_PREFIX(String.class, "shop.prefix"),
@ -113,12 +108,14 @@ public enum ConfigEntry
SHOP_REACTIONS_TIME(Double.class, "shop.reactions.time"),
SHOP_REACTIONS_COINS_PER_WIN(Integer.class, "shop.reactions.coins_per_win"),
SHOP_REACTIONS_STRING_LENGTH(Integer.class, "shop.reactions.string_length"),
SHOP_LOGIN_MESSAGES(List.class, "shop.login_messages"),
SHOP_PRICES_GRAPPLING_HOOK(Integer.class, "shop.prices.grappling_hook"),
SHOP_PRICES_LIGHTNING_ROD(Integer.class, "shop.prices.lightning_rod"),
SHOP_PRICES_FIRE_BALL(Integer.class, "shop.prices.fire_ball"),
SHOP_PRICES_RIDEABLE_PEARL(Integer.class, "shop.prices.rideable_pearl"),
SHOP_PRICES_STACKING_POTATO(Integer.class, "shop.prices.stacking_potato"),
SHOP_PRICES_CLOWN_FISH(Integer.class, "shop.prices.clown_fish"),
SHOP_PRICES_LOGIN_MESSAGES(Integer.class, "shop.prices.login_messages"),
//
STAFFLIST_CLEAN_THESHOLD_HOURS(Integer.class, "stafflist.clean_threshold_hours"),
STAFFLIST_CONSOLE_IS_ADMIN(Boolean.class, "stafflist.console_is_admin"),

View File

@ -7,8 +7,12 @@ import me.totalfreedom.totalfreedommod.rank.Title;
import me.totalfreedom.totalfreedommod.util.FLog;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
@ -20,21 +24,43 @@ public class DiscordToMinecraftListener extends ListenerAdapter
String chat_channel_id = ConfigEntry.DISCORD_CHAT_CHANNEL_ID.getString();
if (event.getMember() != null && !chat_channel_id.isEmpty() && event.getChannel().getId().equals(chat_channel_id))
{
if (!event.getAuthor().getId().equals(Discord.bot.getSelfUser().getId()) && !event.getMessage().getContentDisplay().isEmpty())
if (!event.getAuthor().getId().equals(Discord.bot.getSelfUser().getId()))
{
Member member = event.getMember();
String tag = getDisplay(member);
String message = ChatColor.DARK_GRAY + "[" + ChatColor.DARK_AQUA + "Discord" + ChatColor.DARK_GRAY + "]";
Message msg = event.getMessage();
if (tag != null)
{
message += " " + tag;
}
message += " " + ChatColor.RED + ChatColor.stripColor(member.getEffectiveName()) + ChatColor.DARK_GRAY + ": " + ChatColor.RESET + ChatColor.stripColor(event.getMessage().getContentDisplay());
message += " " + ChatColor.RED + ChatColor.stripColor(member.getEffectiveName()) + ChatColor.DARK_GRAY + ":" + ChatColor.RESET;
ComponentBuilder builder = new ComponentBuilder(message);
if (!msg.getContentDisplay().isEmpty())
{
builder.append(" ").append(ChatColor.stripColor(msg.getContentDisplay()));
message += " " + ChatColor.stripColor(msg.getContentDisplay()); // for logging
}
if (!msg.getAttachments().isEmpty())
{
for (Message.Attachment attachment : msg.getAttachments())
{
if (attachment.getUrl() == null)
{
continue;
}
builder.append(" ");
TextComponent text = new TextComponent(ChatColor.YELLOW + "[Media]");
text.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, attachment.getUrl()));
builder.append(text);
message += " [Media]"; // for logging
}
}
for (Player player : Bukkit.getOnlinePlayers())
{
if (TotalFreedomMod.getPlugin().pl.getData(player).doesDisplayDiscord())
{
player.sendMessage(message);
player.spigot().sendMessage(builder.create());
}
}
FLog.info(message);

View File

@ -256,12 +256,6 @@ public class ItemFun extends FreedomService
break;
}
if (onCooldown(player, ShopItem.CLOWN_FISH))
{
player.sendMessage(ChatColor.RED + "You're currently on a cool-down for 30 seconds.");
break;
}
event.setCancelled(true);
boolean didHit = false;

View File

@ -73,7 +73,7 @@ public class Module_list extends HTTPDModule
operators.add(player.getName());
}
if (!hasSpecialTitle(player) && plugin.sl.isStaff(player))
if (!hasSpecialTitle(player) && plugin.sl.isStaff(player) && !plugin.sl.isVanished(player.getName()))
{
StaffMember staffMember = plugin.sl.getAdmin(player);
switch (staffMember.getRank())
@ -142,7 +142,7 @@ public class Module_list extends HTTPDModule
public boolean hasSpecialTitle(Player player)
{
if (FUtil.DEVELOPERS.contains(player.getName()) || ConfigEntry.SERVER_EXECUTIVES.getList().contains(player.getName()) || ConfigEntry.SERVER_OWNERS.getList().contains(player.getName()))
if (FUtil.DEVELOPERS.contains(player.getUniqueId().toString()) || ConfigEntry.SERVER_EXECUTIVES.getList().contains(player.getName()) || ConfigEntry.SERVER_OWNERS.getList().contains(player.getName()))
{
return true;
}

View File

@ -64,7 +64,7 @@ public class Module_players extends HTTPDModule
masterbuilders.addAll(plugin.pl.getMasterBuilderNames());
// Developers
developers.addAll(FUtil.DEVELOPERS);
developers.addAll(FUtil.DEVELOPER_NAMES);
// Executives
executives.addAll(ConfigEntry.SERVER_EXECUTIVES.getList());

View File

@ -33,8 +33,6 @@ public class PlayerData
private String discordID = null;
private final List<String> backupCodes = Lists.newArrayList();
@Setter
private boolean donator = false;
@Setter
private Boolean masterBuilder = false;
@Setter
private Boolean verification = false;
@ -53,6 +51,9 @@ public class PlayerData
@Getter
@Setter
private String redditUsername;
@Getter
@Setter
private String loginMessage;
public PlayerData(ResultSet resultSet)
{
@ -67,7 +68,6 @@ public class PlayerData
discordID = resultSet.getString("discord_id");
backupCodes.clear();
backupCodes.addAll(FUtil.stringToList(resultSet.getString("backup_codes")));
donator = resultSet.getBoolean("donator");
masterBuilder = resultSet.getBoolean("master_builder");
verification = resultSet.getBoolean("verification");
rideMode = resultSet.getString("ride_mode");
@ -77,6 +77,7 @@ public class PlayerData
totalVotes = resultSet.getInt("total_votes");
displayDiscord = resultSet.getBoolean("display_discord");
redditUsername = resultSet.getString("reddit_username");
loginMessage = resultSet.getString("login_message");
}
catch (SQLException e)
{
@ -104,7 +105,6 @@ public class PlayerData
output.append("Player: ").append(name).append("\n")
.append("- IPs: ").append(StringUtils.join(ips, ", ")).append("\n")
.append("- Discord ID: ").append(discordID).append("\n")
.append("- Donator: ").append(donator).append("\n")
.append("- Master Builder: ").append(masterBuilder).append("\n")
.append("- Has Verification: ").append(verification).append("\n")
.append("- Coins: ").append(coins).append("\n")
@ -113,7 +113,8 @@ public class PlayerData
.append("- Tag: ").append(FUtil.colorize(tag)).append(ChatColor.GRAY).append("\n")
.append("- Ride Mode: ").append(rideMode).append("\n")
.append("- Backup Codes: ").append(backupCodes.size()).append("/10").append("\n")
.append("- Reddit Username: ").append(redditUsername);
.append("- Reddit Username: ").append(redditUsername)
.append("- Login Message: ").append(loginMessage);
return output.toString();
}
@ -128,6 +129,11 @@ public class PlayerData
return Collections.unmodifiableList(ips);
}
public boolean hasLoginMessage()
{
return loginMessage != null && !loginMessage.isEmpty();
}
public boolean addIp(String ip)
{
return !ips.contains(ip) && ips.add(ip);
@ -221,11 +227,6 @@ public class PlayerData
return verification;
}
public boolean isDonator()
{
return donator;
}
public boolean isMasterBuilder()
{
return masterBuilder;
@ -241,7 +242,6 @@ public class PlayerData
put("tag", tag);
put("discord_id", discordID);
put("backup_codes", FUtil.listToString(backupCodes));
put("donator", donator);
put("master_builder", masterBuilder);
put("verification", verification);
put("ride_mode", rideMode);
@ -250,6 +250,7 @@ public class PlayerData
put("total_votes", totalVotes);
put("display_discord", displayDiscord);
put("reddit_username", redditUsername);
put("login_message", loginMessage);
}};
return map;
}

View File

@ -5,6 +5,8 @@ import net.md_5.bungee.api.ChatColor;
public interface Displayable
{
public String getArticle();
public String getName();
public String getTag();
@ -21,7 +23,8 @@ public interface Displayable
public String getColoredLoginMessage();
public boolean hasTeam();
public boolean hasDefaultLoginMessage();
}

View File

@ -5,20 +5,21 @@ import net.md_5.bungee.api.ChatColor;
public enum Rank implements Displayable
{
IMPOSTOR("an", "Impostor", Type.PLAYER, "Imp", ChatColor.YELLOW, null, false),
NON_OP("a", "Non-Op", Type.PLAYER, "", ChatColor.WHITE, null, false),
OP("an", "Operator", Type.PLAYER, "OP", ChatColor.GREEN, null, false),
ADMIN("an", "Admin", Type.STAFF, "Admin", ChatColor.DARK_GREEN, org.bukkit.ChatColor.DARK_GREEN, true),
SENIOR_ADMIN("a", "Senior Admin", Type.STAFF, "SrA", ChatColor.GOLD, org.bukkit.ChatColor.GOLD, true),
ADMIN_CONSOLE("the", "Console", Type.STAFF_CONSOLE, "Console", ChatColor.DARK_PURPLE, null, false),
SENIOR_CONSOLE("the", "Console", Type.STAFF_CONSOLE, "Console", ChatColor.DARK_PURPLE, null, false);
IMPOSTOR("an", "Impostor", Type.PLAYER, "Imp", ChatColor.YELLOW, null, false, false),
NON_OP("a", "Non-Op", Type.PLAYER, "", ChatColor.WHITE, null, false, false),
OP("an", "Operator", Type.PLAYER, "OP", ChatColor.GREEN, null, false, false),
ADMIN("an", "Admin", Type.STAFF, "Admin", ChatColor.DARK_GREEN, org.bukkit.ChatColor.DARK_GREEN, true, true),
SENIOR_ADMIN("a", "Senior Admin", Type.STAFF, "SrA", ChatColor.GOLD, org.bukkit.ChatColor.GOLD, true, true),
ADMIN_CONSOLE("the", "Console", Type.STAFF_CONSOLE, "Console", ChatColor.DARK_PURPLE, null, false, false),
SENIOR_CONSOLE("the", "Console", Type.STAFF_CONSOLE, "Console", ChatColor.DARK_PURPLE, null, false, false);
@Getter
private final Type type;
@Getter
private final String name;
@Getter
private final String abbr;
private final String determiner;
@Getter
private final String article;
@Getter
private final String tag;
@Getter
@ -29,18 +30,21 @@ public enum Rank implements Displayable
private final org.bukkit.ChatColor teamColor;
@Getter
private final boolean hasTeam;
@Getter
private final boolean hasDefaultLoginMessage;
Rank(String determiner, String name, Type type, String abbr, ChatColor color, org.bukkit.ChatColor teamColor, Boolean hasTeam)
Rank(String article, String name, Type type, String abbr, ChatColor color, org.bukkit.ChatColor teamColor, Boolean hasTeam, Boolean hasDefaultLoginMessage)
{
this.type = type;
this.name = name;
this.abbr = abbr;
this.determiner = determiner;
this.article = article;
this.tag = abbr.isEmpty() ? "" : "[" + abbr + "]";
this.coloredTag = abbr.isEmpty() ? "" : ChatColor.DARK_GRAY + "[" + color + abbr + ChatColor.DARK_GRAY + "]" + color;
this.color = color;
this.teamColor = teamColor;
this.hasTeam = hasTeam;
this.hasDefaultLoginMessage = hasDefaultLoginMessage;
}
@Override
@ -52,7 +56,7 @@ public enum Rank implements Displayable
@Override
public String getColoredLoginMessage()
{
return determiner + " " + color + name;
return article + " " + color + name;
}
@Override
@ -61,6 +65,12 @@ public enum Rank implements Displayable
return hasTeam;
}
@Override
public boolean hasDefaultLoginMessage()
{
return hasDefaultLoginMessage;
}
@Override
public String getAbbr()
{

View File

@ -168,7 +168,7 @@ public class RankManager extends FreedomService
FPlayer fPlayer = plugin.pl.getPlayer(player);
PlayerData data = plugin.pl.getData(player);
Displayable display = getDisplay(player);
if (plugin.sl.isStaff(player) || data.isMasterBuilder() || data.isDonator() || FUtil.isDeveloper(player))
if (plugin.sl.isStaff(player) || data.isMasterBuilder() || FUtil.isDeveloper(player))
{
String displayName = display.getColor() + player.getName();
player.setPlayerListName(displayName);
@ -237,7 +237,7 @@ public class RankManager extends FreedomService
}
// Broadcast login message
if (isStaff || FUtil.isDeveloper(player) || plugin.pl.getData(player).isMasterBuilder() || plugin.pl.getData(player).isDonator())
if (isStaff || FUtil.isDeveloper(player) || plugin.pl.getData(player).isMasterBuilder() || plugin.pl.getData(player).hasLoginMessage())
{
if (!plugin.sl.isVanished(player.getName()))
{
@ -260,23 +260,32 @@ public class RankManager extends FreedomService
public String craftLoginMessage(Player player, String message)
{
Displayable display = plugin.rm.getDisplay(player);
String loginMessage = ChatColor.AQUA + player.getName() + " is " + display.getColoredLoginMessage();
if (plugin.sl.isStaff(player))
PlayerData playerData = plugin.pl.getData(player);
if (message == null)
{
StaffMember staffMember = plugin.sl.getAdmin(player);
if (staffMember.hasLoginMessage())
if (playerData.hasLoginMessage())
{
if (message == null)
message = playerData.getLoginMessage();
}
else
{
if (display.hasDefaultLoginMessage())
{
message = staffMember.getLoginMessage();
message = "%name% is %art% %coloredrank%";
}
loginMessage = FUtil.colorize(ChatColor.AQUA + (message.contains("%name%") ? "" : player.getName() + " is ")
+ FUtil.colorize(message).replace("%name%", player.getName())
.replace("%rank%", display.getName())
.replace("%coloredrank%", display.getColoredName()));
}
}
return loginMessage;
if (message != null)
{
String loginMessage = FUtil.colorize(ChatColor.AQUA + (message.contains("%name%") ? "" : player.getName() + " is ")
+ FUtil.colorize(message).replace("%name%", player.getName())
.replace("%rank%", display.getName())
.replace("%coloredrank%", display.getColoredName())
.replace("%art%", display.getArticle()));
return loginMessage;
}
return null;
}
public void updatePlayerTeam(Player player)
@ -304,4 +313,4 @@ public class RankManager extends FreedomService
team.addPlayer(player);
}
}
}
}

View File

@ -6,13 +6,14 @@ import net.md_5.bungee.api.ChatColor;
public enum Title implements Displayable
{
MASTER_BUILDER("a", "Master Builder", ChatColor.DARK_AQUA, org.bukkit.ChatColor.DARK_AQUA, "MB", true),
VERIFIED_STAFF("a", "Verified Staff", ChatColor.LIGHT_PURPLE, org.bukkit.ChatColor.LIGHT_PURPLE, "VS", false),
EXECUTIVE("an", "Executive", ChatColor.RED, org.bukkit.ChatColor.RED, "Exec", true),
DEVELOPER("a", "Developer", ChatColor.DARK_PURPLE, org.bukkit.ChatColor.DARK_PURPLE, "Dev", true),
OWNER("the", "Owner", ChatColor.of("#ff0000"), org.bukkit.ChatColor.DARK_RED, "Owner", true);
MASTER_BUILDER("a", "Master Builder", ChatColor.DARK_AQUA, org.bukkit.ChatColor.DARK_AQUA, "MB", true, true),
VERIFIED_STAFF("a", "Verified Staff Member", ChatColor.LIGHT_PURPLE, org.bukkit.ChatColor.LIGHT_PURPLE, "VS", false, true),
EXECUTIVE("an", "Executive", ChatColor.RED, org.bukkit.ChatColor.RED, "Exec", true, true),
DEVELOPER("a", "Developer", ChatColor.DARK_PURPLE, org.bukkit.ChatColor.DARK_PURPLE, "Dev", true, true),
OWNER("the", "Owner", ChatColor.of("#ff0000"), org.bukkit.ChatColor.DARK_RED, "Owner", true, true);
private final String determiner;
@Getter
private final String article;
@Getter
private final String name;
@Getter
@ -27,10 +28,11 @@ public enum Title implements Displayable
private final org.bukkit.ChatColor teamColor;
@Getter
private final boolean hasTeam;
private final boolean hasDefaultLoginMessage;
Title(String determiner, String name, ChatColor color, org.bukkit.ChatColor teamColor, String tag, Boolean hasTeam)
Title(String article, String name, ChatColor color, org.bukkit.ChatColor teamColor, String tag, Boolean hasTeam, Boolean hasDefaultLoginMessage)
{
this.determiner = determiner;
this.article = article;
this.name = name;
this.coloredTag = ChatColor.DARK_GRAY + "[" + color + tag + ChatColor.DARK_GRAY + "]" + color;
this.abbr = tag;
@ -38,6 +40,7 @@ public enum Title implements Displayable
this.color = color;
this.teamColor = teamColor;
this.hasTeam = hasTeam;
this.hasDefaultLoginMessage = hasDefaultLoginMessage;
}
@Override
@ -52,9 +55,15 @@ public enum Title implements Displayable
return hasTeam;
}
@Override
public boolean hasDefaultLoginMessage()
{
return hasDefaultLoginMessage;
}
@Override
public String getColoredLoginMessage()
{
return determiner + " " + color + name;
return article + " " + color + name;
}
}

View File

@ -35,6 +35,7 @@ public class Shop extends FreedomService
public final String prefix = ChatColor.DARK_GRAY + "[" + ChatColor.YELLOW + "Reaction" + ChatColor.DARK_GRAY + "] ";
public BukkitTask countdownTask;
private BossBar countdownBar = null;
private final String LOGIN_MESSAGE_GUI_TITLE = ChatColor.DARK_GREEN + ChatColor.BOLD.toString() + "Login Messages";
@Override
public void onStart()
@ -174,6 +175,27 @@ public class Shop extends FreedomService
return gui;
}
public Inventory generateLoginMessageGUI(Player player)
{
Inventory gui = server.createInventory(null, 36, LOGIN_MESSAGE_GUI_TITLE);
int slot = 0;
for (String loginMessage : ConfigEntry.SHOP_LOGIN_MESSAGES.getStringList())
{
ItemStack icon = new ItemStack(Material.NAME_TAG);
ItemMeta meta = icon.getItemMeta();
meta.setDisplayName(FUtil.colorize(plugin.rm.craftLoginMessage(player, loginMessage)));
icon.setItemMeta(meta);
gui.setItem(slot, icon);
slot++;
}
ItemStack clear = new ItemStack(Material.BARRIER);
ItemMeta meta = clear.getItemMeta();
meta.setDisplayName(ChatColor.RED + "Clear login message");
clear.setItemMeta(meta);
gui.setItem(35, clear);
return gui;
}
public boolean isRealItem(PlayerData data, ShopItem shopItem, PlayerInventory inventory, ItemStack realItem)
{
if (isRealItem(data, shopItem, inventory.getItemInMainHand(), realItem) || isRealItem(data, shopItem, inventory.getItemInOffHand(), realItem))
@ -306,7 +328,7 @@ public class Shop extends FreedomService
}
@EventHandler(priority = EventPriority.HIGH)
public void onInventoryClick(InventoryClickEvent event)
public void onShopGUIClick(InventoryClickEvent event)
{
if (!(event.getWhoClicked() instanceof Player))
{
@ -350,6 +372,44 @@ public class Shop extends FreedomService
}
}
@EventHandler(priority = EventPriority.HIGH)
public void onLoginMessageGUIClick(InventoryClickEvent event)
{
if (!(event.getWhoClicked() instanceof Player))
{
return;
}
Inventory inventory = event.getInventory();
if (inventory.getSize() != 36 || !event.getView().getTitle().equals(LOGIN_MESSAGE_GUI_TITLE))
{
return;
}
event.setCancelled(true);
int slot = event.getSlot();
Player player = (Player)event.getWhoClicked();
PlayerData data = plugin.pl.getData(player);
if (slot == 35)
{
data.setLoginMessage(null);
plugin.pl.save(data);
player.sendMessage(ChatColor.GREEN + "Removed your login message");
}
else
{
String message = ConfigEntry.SHOP_LOGIN_MESSAGES.getStringList().get(slot);
data.setLoginMessage(message);
plugin.pl.save(data);
player.sendMessage(ChatColor.GREEN + "Your login message is now the following:\n" + plugin.rm.craftLoginMessage(player, message));
}
player.closeInventory();
}
public ShopItem getShopItem(int slot)
{
for (ShopItem shopItem : ShopItem.values())

View File

@ -12,17 +12,18 @@ public enum ShopItem
FIRE_BALL("Fire Ball", Material.FIRE_CHARGE, 14, ConfigEntry.SHOP_PRICES_FIRE_BALL, ChatColor.RED, "fireBall", "/fireball"),
RIDEABLE_PEARL("Rideable Ender Pearl", Material.ENDER_PEARL, 16, ConfigEntry.SHOP_PRICES_RIDEABLE_PEARL, ChatColor.DARK_PURPLE, "rideablePearl", "/rideablepearl"),
STACKING_POTATO("Stacking Potato", Material.POTATO, 20, ConfigEntry.SHOP_PRICES_STACKING_POTATO, ChatColor.YELLOW, "stackingPotato", "/stackingpotato"),
CLOWN_FISH("Clown Fish", Material.TROPICAL_FISH, 24, ConfigEntry.SHOP_PRICES_CLOWN_FISH, ChatColor.GOLD, "clownFish", "/clownfish");
CLOWN_FISH("Clown Fish", Material.TROPICAL_FISH, 22, ConfigEntry.SHOP_PRICES_CLOWN_FISH, ChatColor.GOLD, "clownFish", "/clownfish"),
LOGIN_MESSAGES("Login Messages", Material.NAME_TAG, 24, ConfigEntry.SHOP_PRICES_LOGIN_MESSAGES, ChatColor.DARK_GREEN, "loginMessages", "/loginmessage");
/*
Shop GUI Layout:
Dimensions: 9x4 = 36
Key: g = Grappling Hook, l = Lightning Rod, f = Fire Ball, r = Rideable Ender Pearl, s = Stacking Potato, c = Clown Fish, $ = Coins}
Key: g = Grappling Hook, l = Lightning Rod, f = Fire Ball, r = Rideable Ender Pearl, s = Stacking Potato, c = Clown Fish, x = Login Messages $ = Coins}
---------
-g-l-f-r-
--s---c--
--s-c-x--
--------$
*/

View File

@ -82,7 +82,7 @@ public class SQLite extends FreedomService
{
try
{
connection.createStatement().execute("CREATE TABLE `staff` (`username` VARCHAR NOT NULL, `ips` VARCHAR NOT NULL, `rank` VARCHAR NOT NULL, `active` BOOLEAN NOT NULL, `last_login` LONG NOT NULL, `login_message` VARCHAR, `command_spy` BOOLEAN NOT NULL, `potion_spy` BOOLEAN NOT NULL, `ac_format` VARCHAR, `ptero_id` VARCHAR);");
connection.createStatement().execute("CREATE TABLE `staff` (`username` VARCHAR NOT NULL, `ips` VARCHAR NOT NULL, `rank` VARCHAR NOT NULL, `active` BOOLEAN NOT NULL, `last_login` LONG NOT NULL, `command_spy` BOOLEAN NOT NULL, `potion_spy` BOOLEAN NOT NULL, `ac_format` VARCHAR, `ptero_id` VARCHAR);");
}
catch (SQLException e)
{
@ -93,7 +93,7 @@ public class SQLite extends FreedomService
{
try
{
connection.createStatement().execute("CREATE TABLE `players` (`username` VARCHAR NOT NULL, `ips` VARCHAR NOT NULL, `notes` VARCHAR, `tag` VARCHAR, `discord_id` VARCHAR, `backup_codes` VARCHAR, `donator` BOOLEAN NOT NULL, `master_builder` BOOLEAN NOT NULL,`verification` BOOLEAN NOT NULL, `ride_mode` VARCHAR NOT NULL, `coins` INT NOT NULL, `items` VARCHAR, `total_votes` INT NOT NULL, `display_discord` BOOLEAN NOT NULL, `reddit_username` VARCHAR NOT NULL);");
connection.createStatement().execute("CREATE TABLE `players` (`username` VARCHAR NOT NULL, `ips` VARCHAR NOT NULL, `notes` VARCHAR, `tag` VARCHAR, `discord_id` VARCHAR, `backup_codes` VARCHAR, `donator` BOOLEAN NOT NULL, `master_builder` BOOLEAN NOT NULL,`verification` BOOLEAN NOT NULL, `ride_mode` VARCHAR NOT NULL, `coins` INT NOT NULL, `items` VARCHAR, `total_votes` INT NOT NULL, `display_discord` BOOLEAN NOT NULL, `reddit_username` VARCHAR, `login_message` VARCHAR);");
}
catch (SQLException e)
{
@ -141,7 +141,8 @@ public class SQLite extends FreedomService
}
catch (SQLException e)
{
FLog.severe("Failed to update staff member value: " + e.getMessage());
FLog.severe("Failed to update staff member value:");
FLog.severe(e);
}
}
@ -252,7 +253,6 @@ public class SQLite extends FreedomService
statement.setString(3, staffMember.getRank().toString());
statement.setBoolean(4, staffMember.isActive());
statement.setLong(5, staffMember.getLastLogin().getTime());
statement.setString(6, staffMember.getLoginMessage());
statement.setBoolean(7, staffMember.getCommandSpy());
statement.setBoolean(8, staffMember.getPotionSpy());
statement.setString(9, staffMember.getAcFormat());
@ -261,7 +261,8 @@ public class SQLite extends FreedomService
}
catch (SQLException e)
{
FLog.severe("Failed to add staff member: " + e);
FLog.severe("Failed to add staff member:");
FLog.severe(e);
}
}
@ -269,27 +270,28 @@ public class SQLite extends FreedomService
{
try
{
PreparedStatement statement = connection.prepareStatement("INSERT INTO players VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
PreparedStatement statement = connection.prepareStatement("INSERT INTO players VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
statement.setString(1, player.getName());
statement.setString(2, FUtil.listToString(player.getIps()));
statement.setString(3, FUtil.listToString(player.getNotes()));
statement.setString(4, player.getTag());
statement.setString(5, player.getDiscordID());
statement.setString(6, FUtil.listToString(player.getBackupCodes()));
statement.setBoolean(7, player.isDonator());
statement.setBoolean(8, player.isMasterBuilder());
statement.setBoolean(9, player.hasVerification());
statement.setString(10, player.getRideMode());
statement.setInt(11, player.getCoins());
statement.setBoolean(7, player.isMasterBuilder());
statement.setBoolean(8, player.hasVerification());
statement.setString(9, player.getRideMode());
statement.setInt(10, player.getCoins());
statement.setString(12, FUtil.listToString(player.getItems()));
statement.setInt(13, player.getTotalVotes());
statement.setBoolean(14, player.doesDisplayDiscord());
statement.setString(15, player.getRedditUsername());
statement.setString(16, player.getLoginMessage());
statement.executeUpdate();
}
catch (SQLException e)
{
FLog.severe("Failed to add player: " + e);
FLog.severe("Failed to add player:");
FLog.severe(e);
}
}
@ -305,7 +307,8 @@ public class SQLite extends FreedomService
}
catch (SQLException e)
{
FLog.severe("Failed to get staff member by name: " + e);
FLog.severe("Failed to get staff member by name:");
FLog.severe(e);
}
return null;
@ -323,7 +326,8 @@ public class SQLite extends FreedomService
}
catch (SQLException e)
{
FLog.severe("Failed to get player by name: " + e);
FLog.severe("Failed to get player by name:");
FLog.severe(e);
}
return null;
@ -337,7 +341,8 @@ public class SQLite extends FreedomService
}
catch (SQLException e)
{
FLog.severe("Failed to get Master Builders: " + e);
FLog.severe("Failed to get Master Builders:");
FLog.severe(e);
}
return null;
@ -355,7 +360,8 @@ public class SQLite extends FreedomService
}
catch (SQLException e)
{
FLog.severe("Failed to get player by ip: " + e.getMessage());
FLog.severe("Failed to get player by ip:");
FLog.severe(e);
}
return null;
@ -369,7 +375,8 @@ public class SQLite extends FreedomService
}
catch (SQLException e)
{
FLog.severe("Failed to remove staff member: " + e.getMessage());
FLog.severe("Failed to remove staff member:");
FLog.severe(e);
}
}

View File

@ -35,9 +35,6 @@ public class StaffMember
private Date lastLogin = new Date();
@Getter
@Setter
private String loginMessage = null;
@Getter
@Setter
private Boolean commandSpy = false;
@Getter
@Setter
@ -65,7 +62,6 @@ public class StaffMember
this.ips.clear();
this.ips.addAll(FUtil.stringToList(resultSet.getString("ips")));
this.lastLogin = new Date(resultSet.getLong("last_login"));
this.loginMessage = resultSet.getString("login_message");
this.commandSpy = resultSet.getBoolean("command_spy");
this.potionSpy = resultSet.getBoolean("potion_spy");
this.acFormat = resultSet.getString("ac_format");
@ -85,7 +81,6 @@ public class StaffMember
output.append("Staff: ").append(name).append("\n")
.append("- IPs: ").append(StringUtils.join(ips, ", ")).append("\n")
.append("- Last Login: ").append(FUtil.dateToString(lastLogin)).append("\n")
.append("- Custom Login Message: ").append(loginMessage).append("\n")
.append("- Rank: ").append(rank.getName()).append("\n")
.append("- Is Active: ").append(active).append("\n")
.append("- Potion Spy: ").append(potionSpy).append("\n")
@ -104,7 +99,6 @@ public class StaffMember
put("rank", rank.toString());
put("ips", FUtil.listToString(ips));
put("last_login", lastLogin.getTime());
put("login_message", loginMessage);
put("command_spy", commandSpy);
put("potion_spy", potionSpy);
put("ac_format", acFormat);
@ -113,11 +107,6 @@ public class StaffMember
return map;
}
public boolean hasLoginMessage()
{
return loginMessage != null && !loginMessage.isEmpty();
}
// Util IP methods
public void addIp(String ip)
{

View File

@ -56,7 +56,7 @@ public class FUtil
public static final String SAVED_FLAGS_FILENAME = "savedflags.dat";
/* See https://github.com/TotalFreedom/License - None of the listed names may be removed.
Leaving this list here for anyone running TFM on a cracked server:
public static final List<String> DEVELOPERS = Arrays.asList("Madgeek1450", "Prozza", "WickedGamingUK", "Wild1145", "aggelosQQ", "scripthead", "supernt", "Telesphoreo", "CoolJWB");
public static final List<String> DEVELOPERS = Arrays.asList("Madgeek1450", "Prozza", "WickedGamingUK", "Wild1145", "aggelosQQ", "scripthead", "Telesphoreo", "CoolJWB");
*/
public static final List<String> DEVELOPERS = Arrays.asList(
"1156a81a-23fb-435e-9aff-fe9c2ea7e82d", // Madgeek1450
@ -65,10 +65,10 @@ public class FUtil
"604cbb51-842d-4b43-8b0a-d1d7c6cd2869", // Wild1145
"e67d77c4-fff9-4cea-94cc-9f1f1ab7806b", // aggelosQQ
"0061326b-8b3d-44c8-830a-5f2d59f5dc1b", // scripthead
"53b1512e-3481-4702-9f4f-63cb9c8be6a1", // supernt
"78408086-1991-4c33-a571-d8fa325465b2", // Telesphoreo
"67ce0e28-3d6b-469c-ab71-304eec81b614" // CoolJWB
);
public static final List<String> DEVELOPER_NAMES = Arrays.asList("Madgeek1450", "Prozza", "WickedGamingUK", "Wild1145", "aggelosQQ", "scripthead", "Telesphoreo", "CoolJWB");
public static String DATE_STORAGE_FORMAT = "EEE, d MMM yyyy HH:mm:ss Z";
public static final Map<String, ChatColor> CHAT_COLOR_NAMES = new HashMap<>();
public static final List<ChatColor> CHAT_COLOR_POOL = Arrays.asList(

View File

@ -1,847 +0,0 @@
package org.bstats;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;
import javax.net.ssl.HttpsURLConnection;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicePriority;
/**
* bStats collects some data for plugin authors.
* <p>
* Check out https://bStats.org/ to learn more about bStats!
*/
@SuppressWarnings({"WeakerAccess", "unused"})
public class Metrics
{
static
{
// You can use the property to disable the check in your test environment
if (System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false"))
{
// Maven's Relocate is clever and changes strings, too. So we have to use this little "trick" ... :D
final String defaultPackage = new String(
new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'k', 'k', 'i', 't'});
final String examplePackage = new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
// We want to make sure nobody just copy & pastes the example and use the wrong package names
if (Metrics.class.getPackage().getName().equals(defaultPackage) || Metrics.class.getPackage().getName().equals(examplePackage))
{
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
}
}
}
// The version of this bStats class
public static final int B_STATS_VERSION = 1;
// The url to which the data is sent
private static final String URL = "https://bStats.org/submitData/bukkit";
// Is bStats enabled on this server?
private boolean enabled;
// Should failed requests be logged?
private static boolean logFailedRequests;
// Should the sent data be logged?
private static boolean logSentData;
// Should the response text be logged?
private static boolean logResponseStatusText;
// The uuid of the server
private static String serverUUID;
// The plugin
private final Plugin plugin;
// The plugin id
private final int pluginId;
// A list with all custom charts
private final List<CustomChart> charts = new ArrayList<>();
/**
* Class constructor.
*
* @param plugin The plugin which stats should be submitted.
* @param pluginId The id of the plugin.
* It can be found at <a href="https://bstats.org/what-is-my-plugin-id">What is my plugin id?</a>
*/
public Metrics(Plugin plugin, int pluginId)
{
if (plugin == null)
{
throw new IllegalArgumentException("Plugin cannot be null!");
}
this.plugin = plugin;
this.pluginId = pluginId;
// Get the config file
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
File configFile = new File(bStatsFolder, "config.yml");
YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
// Check if the config file exists
if (!config.isSet("serverUuid"))
{
// Add default values
config.addDefault("enabled", true);
// Every server gets it's unique random id.
config.addDefault("serverUuid", UUID.randomUUID().toString());
// Should failed request be logged?
config.addDefault("logFailedRequests", false);
// Should the sent data be logged?
config.addDefault("logSentData", false);
// Should the response text be logged?
config.addDefault("logResponseStatusText", false);
// Inform the server owners about bStats
config.options().header(
"bStats collects some data for plugin authors like how many servers are using their plugins.\n" +
"To honor their work, you should not disable it.\n" +
"This has nearly no effect on the server performance!\n" +
"Check out https://bStats.org/ to learn more :)"
).copyDefaults(true);
try
{
config.save(configFile);
}
catch (IOException ignored)
{
}
}
// Load the data
enabled = config.getBoolean("enabled", true);
serverUUID = config.getString("serverUuid");
logFailedRequests = config.getBoolean("logFailedRequests", false);
logSentData = config.getBoolean("logSentData", false);
logResponseStatusText = config.getBoolean("logResponseStatusText", false);
if (enabled)
{
boolean found = false;
// Search for all other bStats Metrics classes to see if we are the first one
for (Class<?> service : Bukkit.getServicesManager().getKnownServices())
{
try
{
service.getField("B_STATS_VERSION"); // Our identifier :)
found = true; // We aren't the first
break;
}
catch (NoSuchFieldException ignored)
{
}
}
// Register our service
Bukkit.getServicesManager().register(Metrics.class, this, plugin, ServicePriority.Normal);
if (!found)
{
// We are the first!
startSubmitting();
}
}
}
/**
* Checks if bStats is enabled.
*
* @return Whether bStats is enabled or not.
*/
public boolean isEnabled()
{
return enabled;
}
/**
* Adds a custom chart.
*
* @param chart The chart to add.
*/
public void addCustomChart(CustomChart chart)
{
if (chart == null)
{
throw new IllegalArgumentException("Chart cannot be null!");
}
charts.add(chart);
}
/**
* Starts the Scheduler which submits our data every 30 minutes.
*/
private void startSubmitting()
{
final Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags
timer.scheduleAtFixedRate(new TimerTask()
{
@Override
public void run()
{
if (!plugin.isEnabled())
{ // Plugin was disabled
timer.cancel();
return;
}
// Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
// Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
Bukkit.getScheduler().runTask(plugin, () -> submitData());
}
}, 1000 * 60 * 5, 1000 * 60 * 30);
// Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
// WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
// WARNING: Just don't do it!
}
/**
* Gets the plugin specific data.
* This method is called using Reflection.
*
* @return The plugin specific data.
*/
public JsonObject getPluginData()
{
JsonObject data = new JsonObject();
String pluginName = plugin.getDescription().getName();
String pluginVersion = plugin.getDescription().getVersion();
data.addProperty("pluginName", pluginName); // Append the name of the plugin
data.addProperty("id", pluginId); // Append the id of the plugin
data.addProperty("pluginVersion", pluginVersion); // Append the version of the plugin
JsonArray customCharts = new JsonArray();
for (CustomChart customChart : charts)
{
// Add the data of the custom charts
JsonObject chart = customChart.getRequestJsonObject();
if (chart == null)
{ // If the chart is null, we skip it
continue;
}
customCharts.add(chart);
}
data.add("customCharts", customCharts);
return data;
}
/**
* Gets the server specific data.
*
* @return The server specific data.
*/
private JsonObject getServerData()
{
// Minecraft specific data
int playerAmount;
try
{
// Around MC 1.8 the return type was changed to a collection from an array,
// This fixes java.lang.NoSuchMethodError: org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection;
Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
playerAmount = onlinePlayersMethod.getReturnType().equals(Collection.class)
? ((Collection<?>)onlinePlayersMethod.invoke(Bukkit.getServer())).size()
: ((Player[])onlinePlayersMethod.invoke(Bukkit.getServer())).length;
}
catch (Exception e)
{
playerAmount = Bukkit.getOnlinePlayers().size(); // Just use the new method if the Reflection failed
}
int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
String bukkitVersion = Bukkit.getVersion();
String bukkitName = Bukkit.getName();
// OS/Java specific data
String javaVersion = System.getProperty("java.version");
String osName = System.getProperty("os.name");
String osArch = System.getProperty("os.arch");
String osVersion = System.getProperty("os.version");
int coreCount = Runtime.getRuntime().availableProcessors();
JsonObject data = new JsonObject();
data.addProperty("serverUUID", serverUUID);
data.addProperty("playerAmount", playerAmount);
data.addProperty("onlineMode", onlineMode);
data.addProperty("bukkitVersion", bukkitVersion);
data.addProperty("bukkitName", bukkitName);
data.addProperty("javaVersion", javaVersion);
data.addProperty("osName", osName);
data.addProperty("osArch", osArch);
data.addProperty("osVersion", osVersion);
data.addProperty("coreCount", coreCount);
return data;
}
/**
* Collects the data and sends it afterwards.
*/
private void submitData()
{
final JsonObject data = getServerData();
JsonArray pluginData = new JsonArray();
// Search for all other bStats Metrics classes to get their plugin data
for (Class<?> service : Bukkit.getServicesManager().getKnownServices())
{
try
{
service.getField("B_STATS_VERSION"); // Our identifier :)
for (RegisteredServiceProvider<?> provider : Bukkit.getServicesManager().getRegistrations(service))
{
try
{
Object plugin = provider.getService().getMethod("getPluginData").invoke(provider.getProvider());
if (plugin instanceof JsonObject)
{
pluginData.add((JsonObject)plugin);
}
else
{ // old bstats version compatibility
try
{
Class<?> jsonObjectJsonSimple = Class.forName("org.json.simple.JSONObject");
if (plugin.getClass().isAssignableFrom(jsonObjectJsonSimple))
{
Method jsonStringGetter = jsonObjectJsonSimple.getDeclaredMethod("toJSONString");
jsonStringGetter.setAccessible(true);
String jsonString = (String)jsonStringGetter.invoke(plugin);
JsonObject object = new JsonParser().parse(jsonString).getAsJsonObject();
pluginData.add(object);
}
}
catch (ClassNotFoundException e)
{
// minecraft version 1.14+
if (logFailedRequests)
{
this.plugin.getLogger().log(Level.SEVERE, "Encountered unexpected exception", e);
}
}
}
}
catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored)
{
}
}
}
catch (NoSuchFieldException ignored)
{
}
}
data.add("plugins", pluginData);
// Create a new thread for the connection to the bStats server
new Thread(() ->
{
try
{
// Send the data
sendData(plugin, data);
}
catch (Exception e)
{
// Something went wrong! :(
if (logFailedRequests)
{
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
}
}
}).start();
}
/**
* Sends the data to the bStats server.
*
* @param plugin Any plugin. It's just used to get a logger instance.
* @param data The data to send.
* @throws Exception If the request failed.
*/
private static void sendData(Plugin plugin, JsonObject data) throws Exception
{
if (data == null)
{
throw new IllegalArgumentException("Data cannot be null!");
}
if (Bukkit.isPrimaryThread())
{
throw new IllegalAccessException("This method must not be called from the main thread!");
}
if (logSentData)
{
plugin.getLogger().info("Sending data to bStats: " + data);
}
HttpsURLConnection connection = (HttpsURLConnection)new URL(URL).openConnection();
// Compress the data to save bandwidth
byte[] compressedData = compress(data.toString());
// Add headers
connection.setRequestMethod("POST");
connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close");
connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
// Send data
connection.setDoOutput(true);
try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()))
{
outputStream.write(compressedData);
}
StringBuilder builder = new StringBuilder();
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream())))
{
String line;
while ((line = bufferedReader.readLine()) != null)
{
builder.append(line);
}
}
if (logResponseStatusText)
{
plugin.getLogger().info("Sent data to bStats and received response: " + builder);
}
}
/**
* Gzips the given String.
*
* @param str The string to gzip.
* @return The gzipped String.
* @throws IOException If the compression failed.
*/
private static byte[] compress(final String str) throws IOException
{
if (str == null)
{
return null;
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream))
{
gzip.write(str.getBytes(StandardCharsets.UTF_8));
}
return outputStream.toByteArray();
}
/**
* Represents a custom chart.
*/
public static abstract class CustomChart
{
// The id of the chart
final String chartId;
/**
* Class constructor.
*
* @param chartId The id of the chart.
*/
CustomChart(String chartId)
{
if (chartId == null || chartId.isEmpty())
{
throw new IllegalArgumentException("ChartId cannot be null or empty!");
}
this.chartId = chartId;
}
private JsonObject getRequestJsonObject()
{
JsonObject chart = new JsonObject();
chart.addProperty("chartId", chartId);
try
{
JsonObject data = getChartData();
if (data == null)
{
// If the data is null we don't send the chart.
return null;
}
chart.add("data", data);
}
catch (Throwable t)
{
if (logFailedRequests)
{
Bukkit.getLogger().log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t);
}
return null;
}
return chart;
}
protected abstract JsonObject getChartData() throws Exception;
}
/**
* Represents a custom simple pie.
*/
public static class SimplePie extends CustomChart
{
private final Callable<String> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimplePie(String chartId, Callable<String> callable)
{
super(chartId);
this.callable = callable;
}
@Override
protected JsonObject getChartData() throws Exception
{
JsonObject data = new JsonObject();
String value = callable.call();
if (value == null || value.isEmpty())
{
// Null = skip the chart
return null;
}
data.addProperty("value", value);
return data;
}
}
/**
* Represents a custom advanced pie.
*/
public static class AdvancedPie extends CustomChart
{
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public AdvancedPie(String chartId, Callable<Map<String, Integer>> callable)
{
super(chartId);
this.callable = callable;
}
@Override
protected JsonObject getChartData() throws Exception
{
JsonObject data = new JsonObject();
JsonObject values = new JsonObject();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty())
{
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet())
{
if (entry.getValue() == 0)
{
continue; // Skip this invalid
}
allSkipped = false;
values.addProperty(entry.getKey(), entry.getValue());
}
if (allSkipped)
{
// Null = skip the chart
return null;
}
data.add("values", values);
return data;
}
}
/**
* Represents a custom drilldown pie.
*/
public static class DrilldownPie extends CustomChart
{
private final Callable<Map<String, Map<String, Integer>>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable)
{
super(chartId);
this.callable = callable;
}
@Override
public JsonObject getChartData() throws Exception
{
JsonObject data = new JsonObject();
JsonObject values = new JsonObject();
Map<String, Map<String, Integer>> map = callable.call();
if (map == null || map.isEmpty())
{
// Null = skip the chart
return null;
}
boolean reallyAllSkipped = true;
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet())
{
JsonObject value = new JsonObject();
boolean allSkipped = true;
for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet())
{
value.addProperty(valueEntry.getKey(), valueEntry.getValue());
allSkipped = false;
}
if (!allSkipped)
{
reallyAllSkipped = false;
values.add(entryValues.getKey(), value);
}
}
if (reallyAllSkipped)
{
// Null = skip the chart
return null;
}
data.add("values", values);
return data;
}
}
/**
* Represents a custom single line chart.
*/
public static class SingleLineChart extends CustomChart
{
private final Callable<Integer> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SingleLineChart(String chartId, Callable<Integer> callable)
{
super(chartId);
this.callable = callable;
}
@Override
protected JsonObject getChartData() throws Exception
{
JsonObject data = new JsonObject();
int value = callable.call();
if (value == 0)
{
// Null = skip the chart
return null;
}
data.addProperty("value", value);
return data;
}
}
/**
* Represents a custom multi line chart.
*/
public static class MultiLineChart extends CustomChart
{
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable)
{
super(chartId);
this.callable = callable;
}
@Override
protected JsonObject getChartData() throws Exception
{
JsonObject data = new JsonObject();
JsonObject values = new JsonObject();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty())
{
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet())
{
if (entry.getValue() == 0)
{
continue; // Skip this invalid
}
allSkipped = false;
values.addProperty(entry.getKey(), entry.getValue());
}
if (allSkipped)
{
// Null = skip the chart
return null;
}
data.add("values", values);
return data;
}
}
/**
* Represents a custom simple bar chart.
*/
public static class SimpleBarChart extends CustomChart
{
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable)
{
super(chartId);
this.callable = callable;
}
@Override
protected JsonObject getChartData() throws Exception
{
JsonObject data = new JsonObject();
JsonObject values = new JsonObject();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty())
{
// Null = skip the chart
return null;
}
for (Map.Entry<String, Integer> entry : map.entrySet())
{
JsonArray categoryValues = new JsonArray();
categoryValues.add(new JsonPrimitive(entry.getValue()));
values.add(entry.getKey(), categoryValues);
}
data.add("values", values);
return data;
}
}
/**
* Represents a custom advanced bar chart.
*/
public static class AdvancedBarChart extends CustomChart
{
private final Callable<Map<String, int[]>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable)
{
super(chartId);
this.callable = callable;
}
@Override
protected JsonObject getChartData() throws Exception
{
JsonObject data = new JsonObject();
JsonObject values = new JsonObject();
Map<String, int[]> map = callable.call();
if (map == null || map.isEmpty())
{
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, int[]> entry : map.entrySet())
{
if (entry.getValue().length == 0)
{
continue; // Skip this invalid
}
allSkipped = false;
JsonArray categoryValues = new JsonArray();
for (int categoryValue : entry.getValue())
{
categoryValues.add(new JsonPrimitive(categoryValue));
}
values.add(entry.getKey(), categoryValues);
}
if (allSkipped)
{
// Null = skip the chart
return null;
}
data.add("values", values);
return data;
}
}
}

View File

@ -146,6 +146,25 @@ shop:
# How long is the random string (in characters)?
string_length: 10
# Login messages. Use %name% for usernames, and %rank% for ranks/titles
login_messages:
- '%name% is a terrible %coloredrank%'
- 'that %name% dude is a shitty %coloredrank%'
- 'Hi, my name is %name% and I''m %art% %coloredrank%&b that wasted coins on this login message.'
- '&aDo not fear, %coloredrank% &b%name% &ais here!'
- '%name% is %art% %coloredrank%&b, say hi to them before they gets banned for doing something stupid'
- 'Oh. It''s &l%name%&r&b the %coloredrank%&b again. Great.'
- 'Make way for %name% the %coloredrank%&b!'
- 'It''s a bird! It''s a plane! No, it''s %art% %rank%! It''s %name%'
- '%rank% %name%'
- '%coloredrank%&b %name%'
- 'A wild %name%, %art% %coloredrank%&b, appeared!'
- 'All in all, the %rank% %name% is just another brick in the wall'
- '&a%name% &bis a a geeky &6%rank%'
- '%name% is the %rank% who just exists'
- '%name% based cringe poggers based based %rank%'
- '%name% thinks that &dWindows Server 2019 &bis the best server OS'
# Item prices
prices:
grappling_hook: 100
@ -154,6 +173,7 @@ shop:
rideable_pearl: 700
stacking_potato: 300
clown_fish: 1500
login_messages: 5000
# Staff list
stafflist:
@ -190,12 +210,6 @@ social_links:
Website: 'https://totalfreedom.me/'
Discord: 'https://discordapp.com/invite/XXjmAmV/'
donation:
proboards_url: ''
donator_group_id: ''
session_id: ''
csrf_token: ''
# Blocking certain events
allow:
fire_place: false

View File

@ -60,15 +60,12 @@ master_builders:
- "voxelsniper.goto"
- "voxelsniper.brush.*"
# Trial Mod permission nodes
trial_mods:
# Admin permission nodes
admins:
- "coreprotect.*"
- "worldedit.*"
- "worldguard.*"
- "bending.*"
# Moderator permission nodes
mods: []
# Admin permission nodes
admins: []
# Senior Admin permission nodes
senior_admins: []