Merge pull request #203 from cervinakuy/next-update

v2.2.1
This commit is contained in:
Cervinakuy authored and GitHub committed 2022-11-11 15:56:01 -08:00
commit 5d0f1b3f64
66 files changed
+2326 -2304

No files matched your search

+16 -3
View File
@@ -6,7 +6,7 @@
<groupId>com.planetgallium</groupId>
<artifactId>KitPvP</artifactId>
<version>2.2.0</version>
<version>2.2.1</version>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
@@ -28,6 +28,7 @@
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
@@ -84,7 +85,7 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.18-R0.1-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -108,7 +109,7 @@
<dependency>
<groupId>com.github.cryptomorin</groupId>
<artifactId>XSeries</artifactId>
<version>8.5.0</version>
<version>9.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -123,6 +124,18 @@
<version>3.0.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.36.0.3</version>
<scope>provided</scope> <!-- already shaded in Spigot jar -->
</dependency>
</dependencies>
<repositories>
@@ -0,0 +1,8 @@
package com.planetgallium.database;
public enum DataType {
FIXED_STRING,
STRING,
INTEGER,
FLOAT
}
@@ -0,0 +1,97 @@
package com.planetgallium.database;
import com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import org.sqlite.SQLiteDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
public class Database {
private DataSource dataSource;
private final Map<String, Table> tables;
public Database(String localDatabaseFileName) {
this("none", -1, localDatabaseFileName, "none", "none");
}
public Database(String host, int port, String database, String username, String password) {
this.tables = new HashMap<>();
if (!host.equals("none")) {
setupMySQL(host, port, database, username, password);
} else {
setupSQLite(database);
}
}
private void setupMySQL(String host, int port, String database, String username, String password) {
try {
MysqlDataSource dataSource = new MysqlConnectionPoolDataSource(); // new MysqlDataSource();
dataSource.setServerName(host);
dataSource.setPortNumber(port);
dataSource.setCreateDatabaseIfNotExist(true); // idk
dataSource.setDatabaseName(database);
dataSource.setUser(username);
dataSource.setPassword(password);
this.dataSource = dataSource;
testDatabaseConnection();
} catch (SQLException exception) {
exception.printStackTrace();
System.out.println("[Database] Connection to MySQL database failed. Using SQLite instead...");
setupSQLite("storage.db");
}
}
private void setupSQLite(String databaseFileName) {
SQLiteDataSource sqLiteDataSource = new SQLiteDataSource();
sqLiteDataSource.setUrl("jdbc:sqlite:" + databaseFileName);
this.dataSource = sqLiteDataSource;
}
private void testDatabaseConnection() throws SQLException {
try (Connection connection = dataSource.getConnection()) {
if (!connection.isValid(1)) {
throw new SQLException("Could not establish database connection");
}
}
}
public Table createTable(String tableName, Record masterRecord) {
Table table = new Table(dataSource, tableName, masterRecord);
tables.put(tableName, table);
return table;
}
public void deleteTable(String tableName) {
Table table = tables.get(tableName);
if (table == null) {
System.out.printf("[Database] Failed to delete table %s; table not found\n", tableName);
return;
}
String deleteTableQuery = Table.DELETE_TABLE_QUERY.replace("{table_name}", tableName);
try (Connection connection = dataSource.getConnection() ;
PreparedStatement statement = connection.prepareStatement(deleteTableQuery)) {
statement.executeUpdate();
} catch (SQLException exception) {
exception.printStackTrace();
}
}
public Table getTable(String tableName) {
return tables.get(tableName);
}
public Map<String, Table> getTables() { return tables; }
}
@@ -0,0 +1,54 @@
package com.planetgallium.database;
// aka "column"
public class Field {
private final String name;
private final DataType dataType;
private int limit;
private Object value;
public Field(String name, DataType dataType) {
this.name = name;
this.dataType = dataType;
}
public Field(String name, DataType dataType, Object value) {
this(name, dataType);
this.value = value;
}
public Field(String name, DataType dataType, Object value, int limit) {
this(name, dataType, value);
this.limit = limit;
}
public Field(String name, DataType dataType, int limitOrValue) {
// NOTE: this is a "double-constructor", can work for int data types and strings, but doing different things
this(name, dataType);
if (dataType == DataType.INTEGER || dataType == DataType.FLOAT) {
this.value = limitOrValue;
} else if (dataType == DataType.STRING || dataType == DataType.FIXED_STRING) {
this.limit = limitOrValue;
}
}
public String getSQLDataType() {
switch (this.dataType) {
case FIXED_STRING: return "CHAR";
case STRING: return "VARCHAR";
case INTEGER: return "INT";
case FLOAT: return "FLOAT";
}
return null;
}
public String getName() { return name; }
public DataType getDataType() { return dataType; }
public int getLimit() { return limit; }
public Object getValue() { return value; }
}
@@ -0,0 +1,62 @@
package com.planetgallium.database;
import java.util.*;
// aka a "row" or "line" in a table
public class Record {
private final List<Field> fields;
public Record() {
this.fields = new ArrayList<>();
}
public Record(Field ... fields) {
this.fields = new ArrayList<>();
this.fields.addAll(Arrays.asList(fields));
}
/**
* Adds data to a row. If a column is already present, its data will
* be updated.
*/
public void addOrUpdateData(String columnName, DataType dataType, Object data) {
Field field = new Field(columnName, dataType, data);
int fieldIndex = getFieldIndexByName(columnName);
if (fieldIndex == -1) {
this.fields.add(field);
} else {
this.fields.set(fieldIndex, field);
}
}
public Object getFieldValue(String fieldName) {
Field field = getFieldByName(fieldName);
if (field != null) {
return field.getValue();
}
return null;
}
private int getFieldIndexByName(String fieldName) {
for (int i = 0; i < this.fields.size(); i++) {
if (fields.get(i).getName().equals(fieldName)) {
return i;
}
}
return -1;
}
private Field getFieldByName(String fieldName) {
int fieldIndex = getFieldIndexByName(fieldName);
if (fieldIndex != -1) {
return this.fields.get(fieldIndex);
}
return null;
}
public List<Field> getFields() { return fields; }
public List<Field> getFieldsWithoutPrimaryKey() { return fields.subList(1, fields.size()); }
}
@@ -0,0 +1,320 @@
package com.planetgallium.database;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class Table {
private final static String CREATE_TABLE_QUERY = "CREATE TABLE IF NOT EXISTS {table_name} " +
"({columns_with_data_types}, PRIMARY KEY ({primary_key}));";
public final static String DELETE_TABLE_QUERY = "DROP TABLE IF EXISTS {table_name};";
private final static String INSERT_RECORD_QUERY = "INSERT INTO {table_name} ({columns}) VALUES ({values});";
private final static String UPDATE_RECORD_QUERY = "UPDATE {table_name} SET {columns_with_values} " +
"WHERE `{primary_key}`='{primary_key_value}';";
private final static String SEARCH_RECORD_QUERY = "SELECT * FROM {table_name} WHERE {column_to_search_name}=?;";
private final static String GET_RECORD_QUERY = "SELECT * FROM {table_name} WHERE `{primary_field_name}`=?;";
private final static String DELETE_RECORD_QUERY = "DELETE FROM {table_name} WHERE `{primary_field_name}`=?;";
private final static String TOP_N_RECORD_QUERY = "SELECT {return_column_name}, {sort_column_name} FROM " +
"{table_name} ORDER BY {sort_column_name} DESC LIMIT {n};";
private final DataSource dataSource;
private final String name;
private final Record masterRecord;
private final Field primaryKey;
public Table(DataSource dataSource, String name, Record masterRecord) {
this.dataSource = dataSource;
this.name = name;
this.masterRecord = masterRecord;
this.primaryKey = masterRecord.getFields().get(0);
String createTableQuery = Table.CREATE_TABLE_QUERY.replace("{table_name}", this.getName())
.replace("{columns_with_data_types}", formatFieldNamesWithDataTypes(masterRecord))
.replace("{primary_key}", primaryKey.getName());
try (Connection connection = dataSource.getConnection() ;
PreparedStatement statement = connection.prepareStatement(createTableQuery)) {
statement.executeUpdate();
} catch (SQLException exception) {
exception.printStackTrace();
}
}
public void insertRecord(Field ... fields) {
if (!fields[0].getName().equals(primaryKey.getName())) {
System.out.printf("[Database] Failed to insert record; primary key %s does not match table key\n",
fields[0].getName());
return;
}
Record record = new Record();
for (Field field : fields) {
record.addOrUpdateData(field.getName(), field.getDataType(), field.getValue());
}
insertRecord(record);
}
public void insertRecord(Record recordToInsert) {
if (getRecord(recordToInsert.getFields().get(0)) != null) {
System.out.printf("[Database] Failed to perform action with record %s; already present in database\n",
recordToInsert.getFields().get(0).getName());
return;
}
String columns = String.join(", ", recordFieldsToList(recordToInsert, true));
String values = String.join(", ", recordFieldsToList(recordToInsert, false));
String insertRecordQuery = Table.INSERT_RECORD_QUERY.replace("{table_name}", this.getName())
.replace("{columns}", columns)
.replace("{values}", values);
try (Connection connection = dataSource.getConnection() ;
PreparedStatement statement = connection.prepareStatement(insertRecordQuery)) {
for (int i = 0; i < recordToInsert.getFields().size(); i++) {
Field field = recordToInsert.getFields().get(i);
setStatementParameterToType(statement, i + 1, field);
}
statement.executeUpdate();
} catch (SQLException exception) {
exception.printStackTrace();
}
}
/**
* Updates an existing record (row).
* If the fields parameter contains the primary key field (ex: uuid), it will update its key value to that
* given in the fields
* It will NOT change the primary key column for all database entries in any way
*/
public void updateRecord(Field keyOfRecordToUpdate, Field ... fields) {
if (!containsPrimaryKey(fields)) {
String updateQuery = Table.UPDATE_RECORD_QUERY.replace("{table_name}", this.getName())
.replace("{columns_with_values}", formatFieldNamesWithValues(fields))
.replace("{primary_key}", primaryKey.getName())
.replace("{primary_key_value}", keyOfRecordToUpdate.getValue().toString());
try (Connection connection = dataSource.getConnection() ;
PreparedStatement statement = connection.prepareStatement(updateQuery)) {
statement.executeUpdate();
} catch (SQLException exception) {
exception.printStackTrace();
}
} else {
Record newUpdatedRecord = getRecord(keyOfRecordToUpdate);
for (Field field : fields) {
newUpdatedRecord.addOrUpdateData(field.getName(), field.getDataType(), field.getValue());
}
deleteRecord(keyOfRecordToUpdate);
insertRecord(newUpdatedRecord);
}
}
public void updateRecord(Record record) {
Field keyOfRecordToUpdate = record.getFields().get(0); // NOTE: assuming first field is always key
List<Field> fieldsWithoutKey = record.getFieldsWithoutPrimaryKey();
updateRecord(keyOfRecordToUpdate, fieldsWithoutKey.toArray(new Field[0]));
}
public void updateOrInsertRecord(Record record) {
if (getRecord(record.getFields().get(0)) == null) {
insertRecord(record);
} else {
updateRecord(record);
}
}
/**
* Searches the database for any records with the matching field value. For example, the field value
* could be a username "cervinakuy", of which there should only be 1 record that contains that username
* value. Alternatively, could return a list of multiple elements with all matching records. For example,
* searching the database with the field name "kills" and value 6 would return all the records that have
* 6 kills.
*
* Do NOT use if fieldToSearchFor is the primary key. In that case, use getRecord instead
*/
public List<Record> searchRecords(Field fieldToSearchFor) {
List<Record> matchingRecords = new ArrayList<>();
if (fieldToSearchFor.getName().equals(this.getPrimaryKey().getName())) {
System.out.println("[DATABASE] Primary key search detected. Should use getRecord instead.");
return matchingRecords; // should use getRecord instead
}
String searchQuery = Table.SEARCH_RECORD_QUERY
.replace("{table_name}", this.getName())
.replace("{column_to_search_name}", fieldToSearchFor.getName());
try (Connection connection = dataSource.getConnection() ;
PreparedStatement statement = connection.prepareStatement(searchQuery)) {
setStatementParameterToType(statement, 1, fieldToSearchFor);
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
Record recordResult = new Record();
for (int i = 0; i < masterRecord.getFields().size(); i++) {
Field field = masterRecord.getFields().get(i);
recordResult.addOrUpdateData(field.getName(), field.getDataType(), setObjectType(field, resultSet));
}
matchingRecords.add(recordResult);
}
} catch (SQLException exception) {
exception.printStackTrace();
}
return matchingRecords;
}
public Record getRecord(Field keyToRecord) {
if (!verifyPrimaryKey(this, keyToRecord)) return null;
String getRecordQuery = Table.GET_RECORD_QUERY
.replace("{table_name}", this.getName())
.replace("{primary_field_name}", keyToRecord.getName());
try (Connection connection = dataSource.getConnection() ;
PreparedStatement statement = connection.prepareStatement(getRecordQuery)) {
setStatementParameterToType(statement, 1, keyToRecord);
ResultSet resultSet = statement.executeQuery();
Record recordToReturn = new Record();
if (resultSet.next()) {
for (int i = 0; i < masterRecord.getFields().size(); i++) {
Field field = masterRecord.getFields().get(i);
recordToReturn.addOrUpdateData(field.getName(), field.getDataType(),
setObjectType(field, resultSet));
}
return recordToReturn;
}
} catch (SQLException exception) {
exception.printStackTrace();
}
return null;
}
public void deleteRecord(Field keyOfRecordToDelete) {
if (!verifyPrimaryKey(this, keyOfRecordToDelete)) return;
String deletionQuery = Table.DELETE_RECORD_QUERY.replace("{table_name}", this.getName())
.replace("{primary_field_name}", keyOfRecordToDelete.getName());
try (Connection connection = dataSource.getConnection() ;
PreparedStatement statement = connection.prepareStatement(deletionQuery)) {
setStatementParameterToType(statement, 1, keyOfRecordToDelete);
statement.executeUpdate();
} catch (SQLException exception) {
exception.printStackTrace();
}
}
public List<TopEntry> getTopN(Field sortField, Field returnField, int n) {
String topNQuery = Table.TOP_N_RECORD_QUERY.replace("{table_name}", this.getName())
.replace("{return_column_name}", returnField.getName())
.replace("{sort_column_name}", sortField.getName())
.replace("{n}", String.valueOf(n));
List<TopEntry> topNResults = new ArrayList<>();
try (Connection connection = dataSource.getConnection() ;
PreparedStatement statement = connection.prepareStatement(topNQuery)) {
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
topNResults.add(new TopEntry(resultSet.getString(returnField.getName()),
resultSet.getInt(sortField.getName())));
}
} catch (SQLException exception) {
exception.printStackTrace();
}
return topNResults;
}
private List<String> recordFieldsToList(Record record, boolean fieldNames) {
List<String> fields = new ArrayList<>();
for (Field field : record.getFields()) {
fields.add(fieldNames ? field.getName() : "?");
}
return fields;
}
/**
* Converts columns [fields] (ex: uuid, kills, deaths) to string:
* "uuid VARCHAR, kills INT, deaths INT"
* to be used in SQL statements
*/
private String formatFieldNamesWithDataTypes(Record record) {
String result = "";
for (Field field : record.getFields()) {
result += String.format(", %s %s", field.getName(), field.getSQLDataType());
if (field.getDataType() == DataType.FIXED_STRING ||
field.getDataType() == DataType.STRING) {
result += String.format("(%d)", field.getLimit()); // for "VARCHAR(25)" or "CHAR(25)" for example
}
}
return result.length() > 0 ? result.substring(2) : result;
}
/**
* Converts fields with values (ex: kills=16, experience=85, etc) to one string
* "kills=16 experience=85"
* to be used in SQL statements
*/
private String formatFieldNamesWithValues(Field ... fields) {
String result = "";
for (Field field : fields) {
result += String.format(", %s=%s", field.getName(), field.getValue().toString());
}
return result.length() > 0 ? result.substring(2) : result;
}
private Object setObjectType(Field field, ResultSet resultSet) throws SQLException {
DataType dataType = field.getDataType();
String fieldName = field.getName();
Object data = null;
if (dataType == DataType.STRING) {
data = resultSet.getString(fieldName);
} else if (dataType == DataType.INTEGER) {
data = resultSet.getInt(fieldName);
} else if (dataType == DataType.FLOAT) {
data = resultSet.getFloat(fieldName);
}
return data;
}
private void setStatementParameterToType(PreparedStatement statement, int parameterIndex, Field field)
throws SQLException {
DataType dataType = field.getDataType();
String valueAsString = field.getValue().toString();
if (dataType == DataType.STRING || dataType == DataType.FIXED_STRING) {
statement.setString(parameterIndex, valueAsString);
} else if (dataType == DataType.INTEGER) {
statement.setInt(parameterIndex, Integer.parseInt(valueAsString));
} else if (dataType == DataType.FLOAT) {
statement.setFloat(parameterIndex, Float.parseFloat(valueAsString));
}
}
private boolean verifyPrimaryKey(Table table, Field keyToValidate) {
if (!keyToValidate.getName().equals(table.getPrimaryKey().getName())) {
System.out.printf("[Database] Failed to perform action with key %s; did not match table primary key\n",
keyToValidate.getName());
return false;
}
return true;
}
private boolean containsPrimaryKey(Field ... fields) {
for (Field field : fields) {
if (field.getName().equals(primaryKey.getName())) {
return true;
}
}
return false;
}
public String getName() { return name; }
public Field getPrimaryKey() { return primaryKey; }
}
@@ -0,0 +1,29 @@
package com.planetgallium.database;
public class TopEntry implements Comparable<TopEntry> {
private final String identifier;
private int value;
public TopEntry(String identifier, int value) {
this.identifier = identifier;
this.value = value;
}
@Override
public int compareTo(TopEntry otherEntry) {
if (otherEntry.getValue() > this.getValue()) {
return -1;
} else if (otherEntry.getValue() < this.getValue()) {
return 1;
}
return 0; // if they're equal, will return 0
}
public void setValue(int newValue) { this.value = newValue; }
public String getIdentifier() { return identifier; }
public int getValue() { return value; }
}
@@ -40,7 +40,7 @@ public class Game extends JavaPlugin implements Listener {
instance = this;
resources = new Resources(this);
prefix = resources.getMessages().getString("Messages.General.Prefix");
prefix = resources.getMessages().fetchString("Messages.General.Prefix");
database = new Infobase(this);
arena = new Arena(this, resources);
@@ -87,12 +87,23 @@ public class Game extends JavaPlugin implements Listener {
hasWorldGuard = true;
}
populateUUIDCacheForOnlinePlayers();
Toolkit.printToConsole("&7[&b&lKIT-PVP&7] &aDone!");
}
private void checkUpdate() {
private void populateUUIDCacheForOnlinePlayers() {
// populates UUID cache if there are players online when doing /reload to avoid a lot of errors related
// to database and UUIDs
if (Bukkit.getOnlinePlayers().size() > 0) {
for (Player player : Bukkit.getOnlinePlayers()) {
CacheManager.getUUIDCache().put(player.getName(), player.getUniqueId().toString());
}
}
}
private void checkUpdate() {
Updater.of(this).resourceId(27107).handleResponse((versionResponse, version) -> {
switch (versionResponse) {
case FOUND_NEW:
@@ -105,12 +116,10 @@ public class Game extends JavaPlugin implements Listener {
break;
}
}).check();
}
@EventHandler
public void onInteract(PlayerInteractEvent e) {
Player p = e.getPlayer();
if (!resources.getConfig().contains("Items.Leave")) {
@@ -128,7 +137,7 @@ public class Game extends JavaPlugin implements Listener {
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("Connect");
String server = resources.getConfig().getString("Items.Leave.BungeeCord.Server");
String server = resources.getConfig().fetchString("Items.Leave.BungeeCord.Server");
out.writeUTF(server);
p.sendPluginMessage(this, "BungeeCord", out.toByteArray());
@@ -145,6 +154,14 @@ public class Game extends JavaPlugin implements Listener {
}
@Override
public void onDisable() {
// for players that haven't died and had their stats pushed
// for (String username : CacheManager.getStatsCache().keySet()) {
// arena.getStats().pushCachedStatsToDatabase(username);
// }
}
public boolean hasPlaceholderAPI() { return hasPlaceholderAPI; }
public boolean hasWorldGuard() { return hasWorldGuard; }
@@ -13,91 +13,72 @@ import java.util.List;
public class Ability {
private String name;
private final String name;
private ItemStack activator;
private Cooldown cooldown;
private String message;
private Sound sound;
private int soundPitch;
private int soundVolume;
private List<PotionEffect> effects;
private List<String> commands;
private final List<PotionEffect> effects;
private final List<String> commands;
public Ability(String name) {
this.name = name;
this.effects = new ArrayList<>();
this.commands = new ArrayList<>();
}
public void setActivator(ItemStack activator) {
this.activator = activator;
}
public void setCooldown(Cooldown cooldown) {
this.cooldown = cooldown;
}
public void setMessage(String message) {
this.message = message;
}
public void setSound(Sound sound, int pitch, int volume) {
this.sound = sound;
this.soundPitch = pitch;
this.soundVolume = volume;
}
public void addEffect(PotionEffectType type, int amplifier, int durationSeconds) {
PotionEffect effect = new PotionEffect(type, durationSeconds * 20, amplifier - 1);
effects.add(effect);
}
public void addCommand(String command) {
commands.add(command);
}
public void toResource(Resource resource, String path) {
String pathPrefix = path + "." + name;
resource.set(pathPrefix + ".Activator.Name", Toolkit.toNormalColorCodes(activator.getItemMeta().getDisplayName()));
resource.set(pathPrefix + ".Activator.Material", activator.getType().toString());
public void toResource(Resource resource) {
resource.set("Activator.Name", Toolkit.toNormalColorCodes(activator.getItemMeta().getDisplayName()));
resource.set("Activator.Material", activator.getType().toString());
if (cooldown != null) {
resource.set(pathPrefix + ".Cooldown.Cooldown", cooldown.formatted(true));
resource.set("Cooldown.Cooldown", cooldown.formatted(true));
}
resource.set(pathPrefix + ".Message.Message", message);
resource.set(pathPrefix + ".Sound.Sound", sound.toString());
resource.set(pathPrefix + ".Sound.Pitch", soundPitch != 0 ? soundPitch : null);
resource.set(pathPrefix + ".Sound.Volume", soundVolume != 0 ? soundVolume : null);
resource.set("Message.Message", message);
resource.set("Sound.Sound", sound.toString());
resource.set("Sound.Pitch", soundPitch != 0 ? soundPitch : null);
resource.set("Sound.Volume", soundVolume != 0 ? soundVolume : null);
for (PotionEffect effect : effects) {
String type = effect.getType().getName();
int amplifierNonZeroBased = effect.getAmplifier() + 1;
int durationSeconds = effect.getDuration() / 20;
resource.set(pathPrefix + ".Effects." + type + ".Amplifier", amplifierNonZeroBased);
resource.set(pathPrefix + ".Effects." + type + ".Duration", durationSeconds);
resource.set("Effects." + type + ".Amplifier", amplifierNonZeroBased);
resource.set("Effects." + type + ".Duration", durationSeconds);
}
resource.set(pathPrefix + ".Commands", commands.toArray());
resource.set("Commands", commands.toArray());
resource.save();
}
public String getName() { return name; }
@@ -1,6 +1,7 @@
package com.planetgallium.kitpvp.api;
import com.planetgallium.kitpvp.Game;
import com.planetgallium.kitpvp.util.Resources;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -14,43 +15,37 @@ import com.planetgallium.kitpvp.util.Toolkit;;
public class EventListener implements Listener {
private Arena arena;
private final Resources resources;
private final Arena arena;
public EventListener(Game plugin) {
this.resources = plugin.getResources();
this.arena = plugin.getArena();
}
@EventHandler
public void onAbility(PlayerInteractEvent e) {
if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) {
if (Toolkit.inArena(e.getPlayer())) {
Player p = e.getPlayer();
if (arena.getKits().hasKit(p.getName())) {
ItemStack currentItem = Toolkit.getMainHandItem(p);
Kit kit = arena.getKits().getKitOfPlayer(p.getName());
if (currentItem.hasItemMeta() && currentItem.getItemMeta().hasDisplayName()) {
Ability ability = kit.getAbilityFromActivator(currentItem);
if (ability != null) {
Bukkit.getPluginManager().callEvent(new PlayerAbilityEvent(p, ability));
e.setCancelled(true);
}
}
if (resources.getConfig().getBoolean("Arena.AbilitiesRequireKit") &&
!arena.getKits().hasKit(p.getName())) {
return; // if "AbilitiesRequireKit" true, and player does not have kit, return
}
ItemStack currentItem = Toolkit.getMainHandItem(p);
if (currentItem.hasItemMeta() && currentItem.getItemMeta().hasDisplayName()) {
Ability abilityResult = arena.getAbilities().getAbilityByActivator(currentItem);
if (abilityResult != null) {
Bukkit.getPluginManager().callEvent(new PlayerAbilityEvent(p, abilityResult));
e.setCancelled(true);
}
}
}
}
}
}
@@ -6,7 +6,6 @@ import com.planetgallium.kitpvp.util.Resource;
import com.planetgallium.kitpvp.util.Toolkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
@@ -23,25 +22,23 @@ public class Kit {
private int level;
private int health;
private final Map<String, Object> options;
private final Map<Integer, ItemStack> inventory;
private final List<PotionEffect> effects;
private final List<Ability> abilities;
private ItemStack helmet;
private ItemStack chestplate;
private ItemStack leggings;
private ItemStack boots;
private ItemStack kitHelmet;
private ItemStack kitChestplate;
private ItemStack kitLeggings;
private ItemStack kitBoots;
private ItemStack offhand;
private ItemStack fill;
public Kit(String name) {
this.name = name;
this.options = new HashMap<>();
this.inventory = new HashMap<>();
this.effects = new ArrayList<>();
this.abilities = new ArrayList<>();
}
public void setPermission(String permission) {
@@ -60,6 +57,12 @@ public class Kit {
this.health = health;
}
public void setOption(String key, Object value) {
// NOTE: using this strategy to pass data rather than using Resources class so
// kit class can be used externally without needing access to Resources
this.options.put(key, value);
}
public void setInventoryItem(int slot, ItemStack item) {
inventory.put(slot, item);
}
@@ -69,24 +72,20 @@ public class Kit {
effects.add(effect);
}
public void addAbility(Ability ability) {
abilities.add(ability);
}
public void setHelmet(ItemStack helmet) {
this.helmet = helmet;
this.kitHelmet = helmet;
}
public void setChestplate(ItemStack chestplate) {
this.chestplate = chestplate;
this.kitChestplate = chestplate;
}
public void setLeggings(ItemStack leggings) {
this.leggings = leggings;
this.kitLeggings = leggings;
}
public void setBoots(ItemStack boots) {
this.boots = boots;
this.kitBoots = boots;
}
public void setOffhand(ItemStack offhand) {
@@ -97,44 +96,56 @@ public class Kit {
this.fill = fill;
}
public Ability getAbilityFromActivator(ItemStack activator) {
for (Ability ability : abilities) {
if (activator.getType() == ability.getActivator().getType()) {
ItemMeta meta = activator.getItemMeta();
if (meta.getDisplayName().equals(ability.getActivator().getItemMeta().getDisplayName())) {
return ability;
}
}
}
return null;
}
public void apply(Player player) {
if (helmet != null) player.getInventory().setHelmet(helmet);
if (chestplate != null) player.getInventory().setChestplate(chestplate);
if (leggings != null) player.getInventory().setLeggings(leggings);
if (boots != null) player.getInventory().setBoots(boots);
List<ItemStack> overflowItems = new ArrayList<>();
boolean addOverflowItems = (Boolean) options.get("AddOverflowItemsOnKit");
if (kitHelmet != null) {
if (player.getInventory().getHelmet() == null) {
player.getInventory().setHelmet(kitHelmet);
} else {
overflowItems.add(kitHelmet);
}
}
if (kitChestplate != null) {
if (player.getInventory().getChestplate() == null) {
player.getInventory().setChestplate(kitChestplate);
} else {
overflowItems.add(kitChestplate);
}
}
if (kitLeggings != null) {
if (player.getInventory().getLeggings() == null) {
player.getInventory().setLeggings(kitLeggings);
} else {
overflowItems.add(kitLeggings);
}
}
if (kitBoots != null) {
if (player.getInventory().getBoots() == null) {
player.getInventory().setBoots(kitBoots);
} else {
overflowItems.add(kitBoots);
}
}
Toolkit.setMaxHealth(player, health);
for (int i = 0; i < 36; i++) {
if (addOverflowItems) {
// if kit wants to put an item in slot i, but slot i in player inventory is already taken
if (inventory.containsKey(i) && player.getInventory().getItem(i) != null) {
overflowItems.add(inventory.get(i)); // add kit item to overflow items
continue; // ignore this kit item, will be accounted for with giveOverflowItems
}
}
if (inventory.get(i) != null) {
player.getInventory().setItem(i, inventory.get(i));
} else {
if (fill != null) {
player.getInventory().setItem(i, fill);
}
}
}
@@ -142,7 +153,46 @@ public class Kit {
player.getInventory().setItemInOffHand(offhand);
}
if (addOverflowItems) {
giveOverflowItems(player, overflowItems);
}
if (fill != null) {
for (int i = 0; i < 36; i++) {
if (player.getInventory().getItem(i) == null) {
player.getInventory().setItem(i, fill);
}
}
}
effects.stream().forEach(effect -> player.addPotionEffect(effect));
}
private void giveOverflowItems(Player p, List<ItemStack> overflowItems) {
for (int i = 0; i < 36; i++) {
if (p.getInventory().getItem(i) == null) { // if empty slot found
if (overflowItems.size() >= 1) {
p.getInventory().setItem(i, overflowItems.get(0));
overflowItems.remove(0);
} else {
return; // if no overflow items left, return out of function
}
}
}
boolean dropRemainingOverflowItems = (Boolean) options.get("DropRemainingOverflowItemsOnKit");
if (dropRemainingOverflowItems) {
for (ItemStack remainingOverflowItem : overflowItems) {
p.getWorld().dropItem(p.getLocation(), remainingOverflowItem);
}
String overflowItemsDropMessage = (String) options.get("Message-OverflowItemsDropped");
p.sendMessage(overflowItemsDropMessage.replace("%number%", String.valueOf(overflowItems.size())));
} else {
String overflowItemsLostMessage = (String) options.get("Message-OverflowItemsLost");
p.sendMessage(overflowItemsLostMessage.replace("%number%", String.valueOf(overflowItems.size())));
}
}
@@ -154,10 +204,10 @@ public class Kit {
resource.set("Kit.Health", health);
resource.save();
AttributeWriter.itemStackToResource(resource, "Inventory.Armor.Helmet", helmet);
AttributeWriter.itemStackToResource(resource, "Inventory.Armor.Chestplate", chestplate);
AttributeWriter.itemStackToResource(resource, "Inventory.Armor.Leggings", leggings);
AttributeWriter.itemStackToResource(resource, "Inventory.Armor.Boots", boots);
AttributeWriter.itemStackToResource(resource, "Inventory.Armor.Helmet", kitHelmet);
AttributeWriter.itemStackToResource(resource, "Inventory.Armor.Chestplate", kitChestplate);
AttributeWriter.itemStackToResource(resource, "Inventory.Armor.Leggings", kitLeggings);
AttributeWriter.itemStackToResource(resource, "Inventory.Armor.Boots", kitBoots);
for (Integer slot : inventory.keySet()) {
AttributeWriter.itemStackToResource(resource, "Inventory.Items." + slot, inventory.get(slot));
@@ -170,8 +220,6 @@ public class Kit {
AttributeWriter.potionEffectToResource(resource, "Effects", effect);
}
abilities.stream().forEach(ability -> ability.toResource(resource, "Abilities."));
resource.save();
}
@@ -190,15 +238,13 @@ public class Kit {
public List<PotionEffect> getEffects() { return effects; }
public List<Ability> getAbilities() { return abilities; }
public ItemStack getHelmet() { return kitHelmet; }
public ItemStack getHelmet() { return helmet; }
public ItemStack getChestplate() { return kitChestplate; }
public ItemStack getChestplate() { return chestplate; }
public ItemStack getLeggings() { return kitLeggings; }
public ItemStack getLeggings() { return leggings; }
public ItemStack getBoots() { return boots; }
public ItemStack getBoots() { return kitBoots; }
public ItemStack getFill() { return fill; }
@@ -9,7 +9,7 @@ import org.bukkit.event.player.PlayerCommandPreprocessEvent;
public class AliasCommand implements Listener {
private Resource config;
private final Resource config;
public AliasCommand(Game plugin) {
this.config = plugin.getResources().getConfig();
@@ -17,24 +17,20 @@ public class AliasCommand implements Listener {
@EventHandler
public void onCommand(PlayerCommandPreprocessEvent e) {
Player p = e.getPlayer();
String message = e.getMessage();
String[] words = message.split(" ");
if (message.equals("/spawn") && config.getBoolean("Commands.Alias.Spawn")) {
e.setCancelled(true);
p.performCommand("kp spawn");
} else if (message.equals("/kits") && config.getBoolean("Commands.Alias.Kits")) {
e.setCancelled(true);
p.performCommand("kp kits");
} else if (message.startsWith("/kit") && config.getBoolean("Commands.Alias.Kit")) {
if (words.length == 1) {
e.setCancelled(true);
p.performCommand("kp kit");
@@ -44,7 +40,6 @@ public class AliasCommand implements Listener {
}
} else if (message.startsWith("/stats") && config.getBoolean("Commands.Alias.Stats")) {
if (words.length == 1) {
e.setCancelled(true);
p.performCommand("kp stats");
@@ -52,9 +47,8 @@ public class AliasCommand implements Listener {
e.setCancelled(true);
p.performCommand("kp stats " + words[1]);
}
}
}
}
@@ -43,451 +43,462 @@ public class MainCommand implements CommandExecutor {
public boolean onCommand(CommandSender sender, Command command, String alias, String[] args) {
if (args.length == 0) {
sender.sendMessage(Toolkit.translate("&7[&b&lKIT-PVP&7]"));
sender.sendMessage(Toolkit.translate("&7Version: &b" + plugin.getDescription().getVersion()));
sender.sendMessage(Toolkit.translate("&7Developer: &bCervinakuy"));
sender.sendMessage(Toolkit.translate("&7Commands: &b/kp help"));
sender.sendMessage(Toolkit.translate("&7Download: &bbit.ly/KP-Download"));
executeInfoCommand(sender);
return true;
} else if (args.length == 1) {
if (args[0].equalsIgnoreCase("help")) {
sender.sendMessage(Toolkit.translate("&3&m &r &b&lKIT-PVP &3Created by Cervinakuy &3&m "));
sender.sendMessage(Toolkit.translate(" "));
sender.sendMessage(Toolkit.translate("&7- &b/kp &7Displays information about KitPvP."));
sender.sendMessage(Toolkit.translate("&7- &b/kp help &7Displays the help message."));
sender.sendMessage(Toolkit.translate("&7- &b/kp reload &7Reloads the configuration files."));
sender.sendMessage(Toolkit.translate("&7- &b/kp debug &7Prints debug information."));
sender.sendMessage(Toolkit.translate("&7- &b/kp addspawn &7Adds a spawn to an arena."));
sender.sendMessage(Toolkit.translate("&7- &b/kp arena <arena> &7Teleports you to a different arena."));
sender.sendMessage(Toolkit.translate("&7- &b/kp delarena &7Removes an arena."));
sender.sendMessage(Toolkit.translate("&7- &b/kp spawn &7Teleports you to the local arena spawn."));
sender.sendMessage(Toolkit.translate("&7- &b/kp create <kitName> &7Creates a kit from your inventory."));
sender.sendMessage(Toolkit.translate("&7- &b/kp delete <kitName> &7Deletes an existing kit."));
sender.sendMessage(Toolkit.translate("&7- &b/kp preview <kitName> &7Preview the contents of a kit."));
sender.sendMessage(Toolkit.translate("&7- &b/kp kits &7Lists all available kits."));
sender.sendMessage(Toolkit.translate("&7- &b/kp kit <kitName> &7Select a kit."));
sender.sendMessage(Toolkit.translate("&7- &b/kp kit <kitName> <player> &7Attempts to select a kit for a player."));
sender.sendMessage(Toolkit.translate("&7- &b/kp clear &7Clears your current kit."));
sender.sendMessage(Toolkit.translate("&7- &b/kp clear <player> &7Clears a kit for a player."));
sender.sendMessage(Toolkit.translate("&7- &b/kp stats &7View your stats."));
sender.sendMessage(Toolkit.translate("&7- &b/kp stats <player> &7View the stats of another player."));
sender.sendMessage(Toolkit.translate("&7- &b/kp menu &7Displays the kits menu."));
sender.sendMessage(Toolkit.translate("&7- &b/kp setstats <player> <type> <amount> &7Change stats of a player."));
sender.sendMessage(Toolkit.translate("&7- &b/kp export &7Exports all stats to the new storage format."));
sender.sendMessage(Toolkit.translate(" "));
sender.sendMessage(Toolkit.translate("&3&m "));
executeHelpCommand(sender);
return true;
} else if (args[0].equalsIgnoreCase("reload") && hasPermission(sender, "kp.command.reload")) {
resources.reload();
CacheManager.clearCaches();
arena.getMenus().getKitMenu().clearCache();
sender.sendMessage(messages.getString("Messages.Commands.Reload"));
executeReloadCommand(sender);
return true;
} else if (args[0].equalsIgnoreCase("debug") && hasPermission(sender, "kp.command.debug")) {
String names = "";
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
names += plugin.getName() + " ";
}
sender.sendMessage(Toolkit.translate("&7[&b&lKIT-PVP&7] &aServer Version: &7" + Bukkit.getBukkitVersion()) + " " + (Bukkit.getVersion().contains("Spigot") ? "(Spigot)" : "(Other)"));
sender.sendMessage(Toolkit.translate("&7[&b&lKIT-PVP&7] &aPlugin Version: " + plugin.getDescription().getVersion() + " " + (plugin.needsUpdate() ? "&c(Requires Update)" : "&a(Latest Version)")));
sender.sendMessage(Toolkit.translate("&7[&b&lKIT-PVP&7] &aSpawn Set: " + (config.contains("Arenas") ? "&aConfigured" : "&cUnconfigured")));
sender.sendMessage(Toolkit.translate("&7[&b&lKIT-PVP&7] &aSupport Discord: &7https://discord.gg/Hfej6UR8Bk"));
sender.sendMessage(Toolkit.translate("&7[&b&lKIT-PVP&7] &aPlugin List: &7" + names));
executeDebugCommand(sender);
return true;
} else if (args[0].equalsIgnoreCase("export") && hasPermission(sender, "kp.command.export")) {
File statsFile = new File(plugin.getDataFolder().getAbsolutePath() + "/stats.yml");
if (statsFile.exists()) {
sender.sendMessage(Toolkit.translate("%prefix% &7Exporting data, this may take a while..."));
new BukkitRunnable() {
@Override
public void run() {
plugin.getDatabase().exportStats();
}
}.runTaskAsynchronously(plugin);
sender.sendMessage(Toolkit.translate("%prefix% &aStats successfully exported to database."));
} else {
sender.sendMessage(Toolkit.translate("%prefix% &cNo stats.yml was found to export from."));
}
executeExportCommand(sender);
return true;
} else if (args[0].equalsIgnoreCase("kits") && hasPermission(sender, "kp.command.kits")) {
String message = "";
for (String kitName : resources.getKitList(false)) {
String[] fileName = kitName.split(".yml", 2);
message += fileName[0] + ", ";
}
message = message.substring(0, message.length() - 2);
sender.sendMessage(messages.getString("Messages.Commands.Kits").replace("%kits%", message));
executeKitsCommand(sender);
return true;
}
} else if (args.length == 2) {
if (args[0].equalsIgnoreCase("clear") && hasPermission(sender, "kp.command.clear.other")) {
String playerName = args[1];
Player target = Bukkit.getPlayer(playerName);
if (target != null && Toolkit.inArena(target)) {
clearKit(target);
target.sendMessage(messages.getString("Messages.Commands.Cleared"));
sender.sendMessage(messages.getString("Messages.Commands.ClearedOther").replace("%player%", target.getName()));
} else {
sender.sendMessage(messages.getString("Messages.Error.Offline"));
}
executeClearCommandOther(sender, args);
return true;
} else if (args[0].equalsIgnoreCase("delete") && hasPermission(sender, "kp.command.delete")) {
String kitName = args[1];
if (arena.getKits().isKit(kitName)) {
arena.getKits().deleteKit(kitName);
sender.sendMessage(messages.getString("Messages.Commands.Delete")
.replace("%kit%", kitName));
} else {
sender.sendMessage(messages.getString("Messages.Error.Lost"));
}
executeDeleteKitCommand(sender, args);
return true;
} else if (args[0].equalsIgnoreCase("stats") && hasPermission(sender, "kp.command.stats.other")) {
String targetName = args[1];
if (plugin.getDatabase().databaseTableContainsPlayer("stats", targetName)) {
sendStatsMessage(sender, targetName);
} else {
sender.sendMessage(messages.getString("Messages.Error.Offline"));
}
executeStatsCommandOther(sender, args);
return true;
}
} else if (args.length == 3) {
if (args[0].equalsIgnoreCase("kit") && hasPermission(sender, "kp.command.kit.other")) {
String kitName = args[1];
String playerName = args[2];
Player target = Bukkit.getPlayer(playerName);
if (target != null && Toolkit.inArena(target)) {
Kit kitToGive = arena.getKits().getKitByName(kitName);
arena.getKits().attemptToGiveKitToPlayer(target, kitToGive);
sender.sendMessage(messages.getString("Messages.Commands.KitOther").replace("%player%", playerName).replace("%kit%", kitName));
} else {
sender.sendMessage(messages.getString("Messages.Error.Offline"));
}
executeKitCommand(sender, args);
return true;
}
} else if (args.length == 4) {
if (args[0].equalsIgnoreCase("setstats") && hasPermission(sender, "kp.command.setstats")) {
String playerName = args[1];
String statsIdentifier = args[2];
String possibleAmount = args[3];
if (statsIdentifier.equalsIgnoreCase("kills") ||
statsIdentifier.equalsIgnoreCase("deaths") ||
statsIdentifier.equalsIgnoreCase("level") ||
statsIdentifier.equalsIgnoreCase("experience")) {
if (StringUtils.isNumeric(possibleAmount)) {
String playerUUID = plugin.getDatabase().usernameToUUID(playerName);
if (playerUUID != null) {
int amount = Integer.parseInt(possibleAmount);
arena.getStats().setStat(statsIdentifier, playerName, amount);
sender.sendMessage(resources.getMessages().getString("Messages.Commands.SetStats")
.replace("%player%", playerName)
.replace("%amount%", String.valueOf(amount))
.replace("%type%", statsIdentifier));
return true;
} else {
sender.sendMessage(resources.getMessages().getString("Messages.Error.Offline"));
}
} else {
sender.sendMessage(resources.getMessages().getString("Messages.Error.InvalidNumber")
.replace("%number%", possibleAmount));
}
} else {
sender.sendMessage(resources.getMessages().getString("Messages.Error.InvalidType")
.replace("%type%", statsIdentifier)
.replace("%types%", "kills, deaths, level, experience"));
}
executeSetStatsCommand(sender, args);
return true;
}
}
if (sender instanceof Player) {
Player p = (Player) sender;
if (args.length == 1) {
if (args[0].equalsIgnoreCase("stats") && hasPermission(sender, "kp.command.stats")) {
sendStatsMessage(p, p.getName());
executeStatsCommandSelf(p);
return true;
} else if (args[0].equalsIgnoreCase("menu") && hasPermission(sender, "kp.command.menu")) {
arena.getMenus().getKitMenu().open(p);
executeMenuCommand(p);
return true;
} else if (args[0].equalsIgnoreCase("spawn") && hasPermission(sender, "kp.command.spawn")) {
if (config.contains("Arenas." + p.getWorld().getName())) {
if (!spawnUsers.contains(p.getName())) {
spawnUsers.add(p.getName());
p.sendMessage(messages.getString("Messages.Commands.Teleporting"));
XSound.play(p, "ENTITY_ITEM_PICKUP, 1, -1");
Location beforeLocation = p.getLocation();
new BukkitRunnable() {
public int time = config.getInt("Spawn.Time") + 1;
@Override
public void run() {
time--;
if (time != 0) {
if (p.getGameMode() != GameMode.SPECTATOR) {
p.sendMessage(messages.getString("Messages.Commands.Time").replace("%time%", String.valueOf(time)));
XSound.play(p, "BLOCK_NOTE_BLOCK_SNARE, 1, 1");
if (beforeLocation.getBlockX() != p.getLocation().getBlockX() || beforeLocation.getBlockY() != p.getLocation().getBlockY() || beforeLocation.getBlockZ() != p.getLocation().getBlockZ()) {
p.sendMessage(messages.getString("Messages.Error.Moved"));
spawnUsers.remove(p.getName());
cancel();
}
} else {
spawnUsers.remove(p.getName());
cancel();
}
} else {
p.sendMessage(messages.getString("Messages.Commands.Teleport"));
arena.toSpawn(p, p.getWorld().getName());
if (config.getBoolean("Arena.ClearKitOnCommandSpawn")) {
clearKit(p);
}
spawnUsers.remove(p.getName());
XSound.play(p, "ENTITY_ENDERMAN_TELEPORT, 1, 1");
cancel();
}
}
}.runTaskTimer(plugin, 0L, 20L);
}
} else {
p.sendMessage(messages.getString("Messages.Error.Arena").replace("%arena%", p.getWorld().getName()));
}
executeSpawnCommand(p);
return true;
} else if (args[0].equalsIgnoreCase("clear") && hasPermission(sender, "kp.command.clear")) {
clearKit(p);
p.sendMessage(messages.getString("Messages.Commands.Cleared"));
executeClearCommandSelf(p);
return true;
} else if (args[0].equalsIgnoreCase("addspawn") && hasPermission(p, "kp.command.addspawn")) {
String arenaName = p.getWorld().getName();
int spawnNumber = Toolkit.getNextAvailable(config, "Arenas." + arenaName, 1000, false, 1);
Toolkit.saveLocationToResource(config, "Arenas." + arenaName + "." + spawnNumber, p.getLocation());
p.sendMessage(messages.getString("Messages.Commands.Added")
.replace("%number%", String.valueOf(spawnNumber))
.replace("%arena%", arenaName));
XSound.play(p, "ENTITY_ZOMBIE_ATTACK_WOODEN_DOOR, 1, 1");
executeAddSpawnCommand(p);
return true;
} else if (args[0].equalsIgnoreCase("delarena") && hasPermission(sender, "kp.command.delarena")) {
String arenaName = p.getWorld().getName();
if (config.contains("Arenas." + arenaName)) {
config.set("Arenas." + arenaName, null);
plugin.saveConfig();
p.sendMessage(messages.getString("Messages.Commands.Removed").replace("%arena%", arenaName));
XSound.play(p, "ENTITY_ZOMBIE_ATTACK_WOODEN_DOOR, 1, 1");
} else {
p.sendMessage(messages.getString("Messages.Error.Arena"));
}
executeDeleteArenaCommand(p);
return true;
}
} else if (args.length == 2) {
if (args[0].equalsIgnoreCase("arena") && hasPermission(sender, "kp.command.spawn")) {
String arenaName = args[1];
if (resources.getConfig().getBoolean("Arena.PreventArenaSignUseWithKit")) {
if (arena.getKits().hasKit(p.getName())) {
p.sendMessage(messages.getString("Messages.Error.KitInvalid"));
return true;
}
}
arena.toSpawn(p, arenaName);
executeArenaCommand(p, args);
return true;
} else if (args[0].equalsIgnoreCase("preview") && hasPermission(sender, "kp.command.preview")) {
String kitName = args[1];
if (arena.getKits().isKit(kitName)) {
Kit kitToPreview = arena.getKits().getKitByName(kitName);
arena.getMenus().getPreviewMenu().open(p, kitToPreview);
} else {
p.sendMessage(messages.getString("Messages.Error.Lost"));
}
} else if (args[0].equalsIgnoreCase("create") && hasPermission(sender, "kp.command.create")) {
String kitName = args[1];
if (!arena.getKits().isKit(kitName)) {
arena.getKits().createKit(p, kitName);
p.sendMessage(messages.getString("Messages.Commands.Create")
.replace("%kit%", kitName));
} else {
p.sendMessage(messages.getString("Messages.Error.Exists"));
}
} else if (args[0].equalsIgnoreCase("kit")/* && hasPermission(sender, "kp.command.kit")*/) {
if (Toolkit.inArena(p)) {
String kitName = args[1];
Kit kitToGive = arena.getKits().getKitByName(kitName);
arena.getKits().attemptToGiveKitToPlayer(p, kitToGive);
} else {
p.sendMessage(messages.getString("Messages.Error.Location"));
}
executePreviewCommand(p, args);
return true;
} else if (args[0].equalsIgnoreCase("create") && hasPermission(sender, "kp.command.create")) {
executeCreateKitCommand(p, args);
return true;
} else if (args[0].equalsIgnoreCase("kit")) {
executeKitCommandSelf(p, args);
return true;
}
}
} else {
sender.sendMessage(messages.getString("Messages.General.Player"));
sender.sendMessage(messages.fetchString("Messages.General.Player"));
return true;
}
return false;
}
private void executeInfoCommand(CommandSender sender) {
sender.sendMessage(Toolkit.translate("&7[&b&lKIT-PVP&7]"));
sender.sendMessage(Toolkit.translate("&7Version: &b" + plugin.getDescription().getVersion()));
sender.sendMessage(Toolkit.translate("&7Developer: &bCervinakuy"));
sender.sendMessage(Toolkit.translate("&7Commands: &b/kp help"));
sender.sendMessage(Toolkit.translate("&7Download: &bbit.ly/KP-Download"));
}
private void executeHelpCommand(CommandSender sender) {
sender.sendMessage(Toolkit.translate("&3&m &r &b&lKIT-PVP &3Created by Cervinakuy &3&m "));
sender.sendMessage(Toolkit.translate(" "));
sender.sendMessage(Toolkit.translate("&7- &b/kp &7Displays information about KitPvP."));
sender.sendMessage(Toolkit.translate("&7- &b/kp help &7Displays the help message."));
sender.sendMessage(Toolkit.translate("&7- &b/kp reload &7Reloads the configuration files."));
sender.sendMessage(Toolkit.translate("&7- &b/kp debug &7Prints debug information."));
sender.sendMessage(Toolkit.translate("&7- &b/kp addspawn &7Adds a spawn to an arena."));
sender.sendMessage(Toolkit.translate("&7- &b/kp arena <arena> &7Teleports you to a different arena."));
sender.sendMessage(Toolkit.translate("&7- &b/kp delarena &7Removes an arena."));
sender.sendMessage(Toolkit.translate("&7- &b/kp spawn &7Teleports you to the local arena spawn."));
sender.sendMessage(Toolkit.translate("&7- &b/kp create <kitName> &7Creates a kit from your inventory."));
sender.sendMessage(Toolkit.translate("&7- &b/kp delete <kitName> &7Deletes an existing kit."));
sender.sendMessage(Toolkit.translate("&7- &b/kp preview <kitName> &7Preview the contents of a kit."));
sender.sendMessage(Toolkit.translate("&7- &b/kp kits &7Lists all available kits."));
sender.sendMessage(Toolkit.translate("&7- &b/kp kit <kitName> &7Select a kit."));
sender.sendMessage(Toolkit.translate("&7- &b/kp kit <kitName> <player> &7Attempts to select a kit for a player."));
sender.sendMessage(Toolkit.translate("&7- &b/kp clear &7Clears your current kit."));
sender.sendMessage(Toolkit.translate("&7- &b/kp clear <player> &7Clears a kit for a player."));
sender.sendMessage(Toolkit.translate("&7- &b/kp stats &7View your stats."));
sender.sendMessage(Toolkit.translate("&7- &b/kp stats <player> &7View the stats of another player."));
sender.sendMessage(Toolkit.translate("&7- &b/kp menu &7Displays the kits menu."));
sender.sendMessage(Toolkit.translate("&7- &b/kp setstats <player> <type> <amount> &7Change stats of a player."));
sender.sendMessage(Toolkit.translate("&7- &b/kp export &7Exports all stats to the new storage format."));
sender.sendMessage(Toolkit.translate(" "));
sender.sendMessage(Toolkit.translate("&3&m "));
}
private void executeReloadCommand(CommandSender sender) {
resources.reload();
CacheManager.clearCaches();
arena.getMenus().getKitMenu().rebuildCache();
arena.getAbilities().rebuildCache();
sender.sendMessage(messages.fetchString("Messages.Commands.Reload"));
}
private void executeDebugCommand(CommandSender sender) {
String names = "";
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
names += plugin.getName() + " ";
}
sender.sendMessage(Toolkit.translate("&7[&b&lKIT-PVP&7] &aServer Version: &7" + Bukkit.getBukkitVersion()) + " " + (Bukkit.getVersion().contains("Spigot") ? "(Spigot)" : "(Other)"));
sender.sendMessage(Toolkit.translate("&7[&b&lKIT-PVP&7] &aPlugin Version: &7" + plugin.getDescription().getVersion() + " " + (plugin.needsUpdate() ? "&c(Requires Update)" : "&a(Latest Version)")));
sender.sendMessage(Toolkit.translate("&7[&b&lKIT-PVP&7] &aSpawn Set: " + (config.contains("Arenas") ? "&aConfigured" : "&cUnconfigured")));
sender.sendMessage(Toolkit.translate("&7[&b&lKIT-PVP&7] &aSupport Discord: &7https://discord.gg/Hfej6UR8Bk"));
sender.sendMessage(Toolkit.translate("&7[&b&lKIT-PVP&7] &aPlugin List: &7" + names));
}
private void executeExportCommand(CommandSender sender) {
File statsFile = new File(plugin.getDataFolder().getAbsolutePath() + "/stats.yml");
if (statsFile.exists()) {
sender.sendMessage(Toolkit.translate("%prefix% &7Exporting data, this may take a while..."));
new BukkitRunnable() {
@Override
public void run() {
plugin.getDatabase().exportStats();
}
}.runTaskAsynchronously(plugin);
sender.sendMessage(Toolkit.translate("%prefix% &aStats successfully exported to database."));
} else {
sender.sendMessage(Toolkit.translate("%prefix% &cNo stats.yml was found to export from."));
}
}
private void executeKitsCommand(CommandSender sender) {
String message = "";
for (String kitName : resources.getPluginDirectoryFiles("kits", false)) {
String[] fileName = kitName.split(".yml", 2);
message += fileName[0] + ", ";
}
message = message.substring(0, message.length() - 2);
sender.sendMessage(messages.fetchString("Messages.Commands.Kits").replace("%kits%", message));
}
private void executeClearCommandOther(CommandSender sender, String[] args) {
String playerName = args[1];
Player target = Bukkit.getPlayer(playerName);
if (target != null && Toolkit.inArena(target)) {
clearKit(target);
target.sendMessage(messages.fetchString("Messages.Commands.Cleared"));
sender.sendMessage(messages.fetchString("Messages.Commands.ClearedOther").replace("%player%", target.getName()));
} else {
sender.sendMessage(messages.fetchString("Messages.Error.Offline"));
}
}
private void executeDeleteKitCommand(CommandSender sender, String[] args) {
String kitName = args[1];
if (arena.getKits().isKit(kitName)) {
arena.getKits().deleteKit(kitName);
sender.sendMessage(messages.fetchString("Messages.Commands.Delete")
.replace("%kit%", kitName));
} else {
sender.sendMessage(messages.fetchString("Messages.Error.Lost"));
}
}
private void executeStatsCommandOther(CommandSender sender, String[] args) {
String targetName = args[1];
if (plugin.getDatabase().isPlayerRegistered(targetName)) {
sendStatsMessage(sender, targetName);
} else {
sender.sendMessage(messages.fetchString("Messages.Error.Offline"));
}
}
private void executeKitCommand(CommandSender sender, String[] args) {
String kitName = args[1];
String playerName = args[2];
Player target = Bukkit.getPlayer(playerName);
if (target != null && Toolkit.inArena(target)) {
Kit kitToGive = arena.getKits().getKitByName(kitName);
arena.getKits().attemptToGiveKitToPlayer(target, kitToGive);
sender.sendMessage(messages.fetchString("Messages.Commands.KitOther").replace("%player%", playerName).replace("%kit%", kitName));
} else {
sender.sendMessage(messages.fetchString("Messages.Error.Offline"));
}
}
private void executeSetStatsCommand(CommandSender sender, String[] args) {
String playerName = args[1];
String statsIdentifier = args[2];
String possibleAmount = args[3];
if (statsIdentifier.equalsIgnoreCase("kills") ||
statsIdentifier.equalsIgnoreCase("deaths") ||
statsIdentifier.equalsIgnoreCase("level") ||
statsIdentifier.equalsIgnoreCase("experience")) {
if (!StringUtils.isNumeric(possibleAmount)) {
sender.sendMessage(resources.getMessages().fetchString("Messages.Error.InvalidNumber")
.replace("%number%", possibleAmount));
}
String playerUUID = plugin.getDatabase().usernameToUUID(playerName);
if (playerUUID == null) {
sender.sendMessage(resources.getMessages().fetchString("Messages.Error.Offline"));
}
int amount = Integer.parseInt(possibleAmount);
arena.getStats().setStat(statsIdentifier, playerName, amount);
arena.getStats().pushCachedStatsToDatabase(playerName, false);
sender.sendMessage(resources.getMessages().fetchString("Messages.Commands.SetStats")
.replace("%player%", playerName)
.replace("%amount%", String.valueOf(amount))
.replace("%type%", statsIdentifier));
} else {
sender.sendMessage(resources.getMessages().fetchString("Messages.Error.InvalidType")
.replace("%type%", statsIdentifier)
.replace("%types%", "kills, deaths, level, experience"));
}
}
private void executeStatsCommandSelf(Player p) {
sendStatsMessage(p, p.getName());
}
private void executeMenuCommand(Player p) {
arena.getMenus().getKitMenu().open(p);
}
private void executeSpawnCommand(Player p) {
if (!config.contains("Arenas." + p.getWorld().getName())) {
p.sendMessage(messages.fetchString("Messages.Error.Arena").replace("%arena%", p.getWorld().getName()));
return;
}
if (spawnUsers.contains(p.getName())) {
return;
}
p.sendMessage(messages.fetchString("Messages.Commands.Teleporting"));
spawnUsers.add(p.getName());
XSound.play(p, "ENTITY_ITEM_PICKUP, 1, -1");
Location beforeLocation = p.getLocation();
new BukkitRunnable() {
public int time = config.getInt("Spawn.Time") + 1;
@Override
public void run() {
time--;
if (time != 0) {
if (p.getGameMode() != GameMode.SPECTATOR) {
p.sendMessage(messages.fetchString("Messages.Commands.Time")
.replace("%time%", String.valueOf(time)));
XSound.play(p, "BLOCK_NOTE_BLOCK_SNARE, 1, 1");
if (beforeLocation.getBlockX() != p.getLocation().getBlockX() ||
beforeLocation.getBlockY() != p.getLocation().getBlockY() ||
beforeLocation.getBlockZ() != p.getLocation().getBlockZ()) {
p.sendMessage(messages.fetchString("Messages.Error.Moved"));
spawnUsers.remove(p.getName());
cancel();
}
} else {
spawnUsers.remove(p.getName());
cancel();
}
} else {
p.sendMessage(messages.fetchString("Messages.Commands.Teleport"));
arena.toSpawn(p, p.getWorld().getName());
if (config.getBoolean("Arena.ClearKitOnCommandSpawn")) {
clearKit(p);
}
spawnUsers.remove(p.getName());
XSound.play(p, "ENTITY_ENDERMAN_TELEPORT, 1, 1");
cancel();
}
}
}.runTaskTimer(plugin, 0L, 20L);
}
private void executeClearCommandSelf(Player p) {
clearKit(p);
p.sendMessage(messages.fetchString("Messages.Commands.Cleared"));
}
private void executeAddSpawnCommand(Player p) {
String arenaName = p.getWorld().getName();
int spawnNumber = Toolkit.getNextAvailable(config, "Arenas." + arenaName, 1000, false, 1);
Toolkit.saveLocationToResource(config, "Arenas." + arenaName + "." + spawnNumber, p.getLocation());
p.sendMessage(messages.fetchString("Messages.Commands.Added")
.replace("%number%", String.valueOf(spawnNumber))
.replace("%arena%", arenaName));
XSound.play(p, "ENTITY_ZOMBIE_ATTACK_WOODEN_DOOR, 1, 1");
}
private void executeDeleteArenaCommand(Player p) {
String arenaName = p.getWorld().getName();
if (config.contains("Arenas." + arenaName)) {
config.set("Arenas." + arenaName, null);
plugin.saveConfig();
p.sendMessage(messages.fetchString("Messages.Commands.Removed").replace("%arena%", arenaName));
XSound.play(p, "ENTITY_ZOMBIE_ATTACK_WOODEN_DOOR, 1, 1");
} else {
p.sendMessage(messages.fetchString("Messages.Error.Arena"));
}
}
private void executeArenaCommand(Player p, String[] args) {
String arenaName = args[1];
if (resources.getConfig().getBoolean("Arena.PreventArenaSignUseWithKit")) {
if (arena.getKits().hasKit(p.getName())) {
p.sendMessage(messages.fetchString("Messages.Error.KitInvalid"));
return;
}
}
arena.toSpawn(p, arenaName);
}
private void executePreviewCommand(Player p, String[] args) {
String kitName = args[1];
if (arena.getKits().isKit(kitName)) {
Kit kitToPreview = arena.getKits().getKitByName(kitName);
arena.getMenus().getPreviewMenu().open(p, kitToPreview, resources);
} else {
p.sendMessage(messages.fetchString("Messages.Error.Lost"));
}
}
private void executeCreateKitCommand(Player p, String[] args) {
String kitName = args[1];
if (!validateKitName(kitName)) {
p.sendMessage(messages.fetchString("Messages.Error.InvalidKitName"));
return;
}
if (!arena.getKits().isKit(kitName)) {
arena.getKits().createKit(p, kitName);
p.sendMessage(messages.fetchString("Messages.Commands.Create")
.replace("%kit%", kitName));
} else {
p.sendMessage(messages.fetchString("Messages.Error.Exists"));
}
}
private void executeKitCommandSelf(Player p, String[] args) {
if (Toolkit.inArena(p)) {
String kitName = args[1];
Kit kitToGive = arena.getKits().getKitByName(kitName);
arena.getKits().attemptToGiveKitToPlayer(p, kitToGive);
} else {
p.sendMessage(messages.fetchString("Messages.Error.Location"));
}
}
private boolean hasPermission(CommandSender sender, String permission) {
if (sender.hasPermission(permission)) {
return true;
}
sender.sendMessage(messages.getString("Messages.General.Permission").replace("%permission%", permission));
return false;
sender.sendMessage(messages.fetchString("Messages.General.Permission").replace("%permission%", permission));
return false;
}
private void clearKit(Player p) {
p.getInventory().setArmorContents(null);
p.getInventory().clear();
@@ -499,19 +510,23 @@ public class MainCommand implements CommandExecutor {
}
if (config.getBoolean("Arena.GiveItemsOnClear")) {
arena.giveItems(p);
arena.giveArenaItems(p);
}
arena.getKits().resetKit(p.getName());
}
private void sendStatsMessage(CommandSender receiver, String username) {
for (String line : messages.getStringList("Messages.Stats.Message")) {
receiver.sendMessage(arena.replaceBuiltInPlaceholdersIfPresent(line, username));
receiver.sendMessage(arena.getUtilities().replaceBuiltInPlaceholdersIfPresent(line, username));
}
}
private boolean validateKitName(String possibleKitName) {
if (possibleKitName.contains("-") || possibleKitName.contains("+")) {
return false;
}
return true;
}
}
@@ -0,0 +1,101 @@
package com.planetgallium.kitpvp.game;
import com.planetgallium.kitpvp.Game;
import com.planetgallium.kitpvp.api.Ability;
import com.planetgallium.kitpvp.util.Cooldown;
import com.planetgallium.kitpvp.util.Resource;
import com.planetgallium.kitpvp.util.Resources;
import com.planetgallium.kitpvp.util.Toolkit;
import org.bukkit.Sound;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.potion.PotionEffectType;
import java.util.HashMap;
import java.util.Map;
public class Abilities {
private final Resources resources;
private final Map<ItemStack, Ability> activatorToAbility;
public Abilities(Game plugin) {
this.resources = plugin.getResources();
this.activatorToAbility = new HashMap<>();
rebuildCache();
}
public void rebuildCache() {
for (Resource abilityResource : resources.getAbilityResources()) {
Ability ability = getAbilityFromResource(abilityResource);
activatorToAbility.put(ability.getActivator(), ability);
}
}
public Ability getAbilityByActivator(ItemStack potentialActivator) {
for (ItemStack loadedActivator : activatorToAbility.keySet()) {
if (Toolkit.itemStacksMatch(loadedActivator, potentialActivator)) {
return activatorToAbility.get(potentialActivator);
}
}
return null;
}
private Ability getAbilityFromResource(Resource resource) {
Ability ability = new Ability(resource.getName());
// Activator
ItemStack activator = Toolkit.safeItemStack(resource.fetchString("Activator.Material"));
ItemMeta activatorMeta = activator.getItemMeta();
activatorMeta.setDisplayName(resource.fetchString("Activator.Name"));
activator.setItemMeta(activatorMeta);
ability.setActivator(activator);
// Cooldown
if (resource.contains("Cooldown")) {
String formattedCooldown = resource.fetchString("Cooldown.Cooldown");
ability.setCooldown(new Cooldown(formattedCooldown));
}
// Message
if (resource.contains("Message")) {
ability.setMessage(resource.fetchString("Message.Message"));
}
// Sound
if (resource.contains("Sound")) {
Sound abilitySound = Toolkit.safeSound(resource.fetchString("Sound.Sound"));
int abilitySoundPitch = resource.getInt("Sound.Pitch");
int abilitySoundVolume = resource.getInt("Sound.Volume");
ability.setSound(abilitySound, abilitySoundPitch, abilitySoundVolume);
}
// Effects
if (resource.contains("Effects")) {
ConfigurationSection effectSection = resource.getConfigurationSection("Effects");
for (String effectName : effectSection.getKeys(false)) {
PotionEffectType effectType = Toolkit.safePotionEffectType(effectName);
int amplifier = resource.getInt("Effects." + effectName + ".Amplifier");
int duration = resource.getInt("Effects." + effectName + ".Duration");
ability.addEffect(effectType, amplifier, duration);
}
}
// Commands
if (resource.contains("Commands")) {
for (String command : resource.getStringList("Commands")) {
ability.addCommand(command);
}
}
return ability;
}
}
@@ -2,7 +2,6 @@ package com.planetgallium.kitpvp.game;
import java.util.*;
import com.cryptomorin.xseries.XMaterial;
import com.planetgallium.kitpvp.util.*;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
@@ -15,8 +14,6 @@ import org.bukkit.scoreboard.Scoreboard;
import com.planetgallium.kitpvp.Game;
import me.clip.placeholderapi.PlaceholderAPI;
public class Arena {
private final Game plugin;
@@ -27,13 +24,15 @@ public class Arena {
private final Map<String, String> hitCache;
private final Utilities utilties;
private final Leaderboards leaderboards;
private final Stats stats;
private final Kits kits;
private final Abilities abilities;
private final KillStreaks killstreaks;
private final Cooldowns cooldowns;
private final Menus menus;
public Arena(Game plugin, Resources resources) {
this.plugin = plugin;
this.random = new Random();
@@ -43,21 +42,23 @@ public class Arena {
this.hitCache = new HashMap<>();
this.utilties = new Utilities(plugin, this);
this.leaderboards = new Leaderboards(plugin);
this.stats = new Stats(plugin, this);
this.kits = new Kits(plugin, this);
this.abilities = new Abilities(plugin);
this.killstreaks = new KillStreaks(resources);
this.cooldowns = new Cooldowns(plugin);
this.cooldowns = new Cooldowns(plugin, this);
this.menus = new Menus(resources);
}
public void addPlayer(Player p, boolean toSpawn, boolean giveItems) {
CacheManager.getPlayerAbilityCooldowns(p.getName()).clear();
kits.resetKit(p.getName());
if (config.getBoolean("Arena.ResetKillStreakOnLeave")) {
killstreaks.setStreak(p, 0);
}
@@ -82,7 +83,7 @@ public class Arena {
p.setFoodLevel(20);
if (giveItems) {
giveItems(p);
giveArenaItems(p);
}
if (toSpawn) {
@@ -92,11 +93,9 @@ public class Arena {
if (resources.getScoreboard().getBoolean("Scoreboard.General.Enabled")) {
updateScoreboards(p, false);
}
}
public void removePlayer(Player p) {
CacheManager.getPlayerAbilityCooldowns(p.getName()).clear();
for (PotionEffect effect : p.getActivePotionEffects()) {
@@ -120,142 +119,64 @@ public class Arena {
updateScoreboards(p, true);
}
stats.pushCachedStatsToDatabase(p.getName(), false); // cached stats are pushed to database on death
hitCache.remove(p.getName());
}
public void deletePlayer(Player p) {
if (config.getBoolean("Arena.ClearInventoryOnLeave")) {
p.getInventory().clear();
p.getInventory().setArmorContents(null);
}
CacheManager.getPlayerAbilityCooldowns(p.getName()).clear();
hitCache.remove(p.getName());
stats.pushCachedStatsToDatabase(p.getName(), true);
}
public void giveItems(Player p) {
public void giveArenaItems(Player p) {
ConfigurationSection items = config.getConfigurationSection("Items");
for (String identifier : items.getKeys(false)) {
String itemPath = "Items." + identifier;
if (config.getBoolean(itemPath + ".Enabled")) {
ItemStack item = new ItemStack(XMaterial.matchXMaterial(config.getString(itemPath + ".Material")).get().parseMaterial());
ItemStack item = Toolkit.safeItemStack(config.fetchString(itemPath + ".Material"));
ItemMeta meta = item.getItemMeta();
meta.setDisplayName(config.getString(itemPath + ".Name"));
meta.setDisplayName(config.fetchString(itemPath + ".Name"));
item.setItemMeta(meta);
p.getInventory().setItem(config.getInt(itemPath + ".Slot"), item);
}
}
}
public void toSpawn(Player p, String arenaName) {
if (config.contains("Arenas." + arenaName)) {
p.teleport(Toolkit.getLocationFromResource(config, "Arenas." + arenaName + "." + generateRandomArenaSpawn(arenaName)));
p.teleport(Toolkit.getLocationFromResource(config,
"Arenas." + arenaName + "." + generateRandomArenaSpawn(arenaName)));
} else {
p.sendMessage(resources.getMessages().getString("Messages.Error.Arena").replace("%arena%", arenaName));
p.sendMessage(resources.getMessages().fetchString("Messages.Error.Arena")
.replace("%arena%", arenaName));
}
}
public void updateScoreboards(Player p, boolean hide) {
Scoreboard board = Bukkit.getScoreboardManager().getNewScoreboard();
Infoboard scoreboard = new Infoboard(board, resources.getScoreboard().getString("Scoreboard.General.Title"));
String scoreboardTitle = utilties.addPlaceholdersIfPossible(p,
resources.getScoreboard().fetchString("Scoreboard.General.Title"));
Infoboard scoreboard = new Infoboard(board, scoreboardTitle);
if (!hide) {
for (String line : resources.getScoreboard().getStringList("Scoreboard.Lines")) {
scoreboard.add(addPlaceholdersIfPossible(p, line));
scoreboard.add(utilties.addPlaceholdersIfPossible(p, line));
}
} else {
scoreboard.hide();
}
scoreboard.update(p);
}
private String addPlaceholdersIfPossible(Player p, String text) {
if (plugin.hasPlaceholderAPI()) {
text = PlaceholderAPI.setPlaceholders(p, text);
}
return replaceBuiltInPlaceholdersIfPresent(text, p.getName());
}
public String replaceBuiltInPlaceholdersIfPresent(String s, String username) {
// The reason I'm doing all these if statements rather than a more concise code solution is to reduce
// the amount of data that is unnecessarily fetched (ex by using .replace) to improve performance
// no longer constantly fetching stats from database for EACH line of scoreboard on update and player join
if (s.contains("%streak%")) {
s = s.replace("%streak%", String.valueOf(getKillStreaks().getStreak(username)));
}
if (s.contains("%player%")) {
s = s.replace("%player%", username);
}
if (s.contains("%xp%")) {
s = s.replace("%xp%", String.valueOf(stats.getStat("experience", username)));
}
if (s.contains("%level%")) {
s = s.replace("%level%", String.valueOf(stats.getStat("level", username)));
}
if (s.contains("%max_xp%")) {
s = s.replace("%max_xp%", String.valueOf(stats.getRegularOrRelativeNeededExperience(username)));
}
if (s.contains("%max_level%")) {
s = s.replace("%max_level%", String.valueOf(resources.getLevels().getInt("Levels.Options.Maximum-Level")));
}
if (s.contains("%kd%")) {
s = s.replace("%kd%", String.valueOf(getStats().getKDRatio(username)));
}
if (s.contains("%kills%")) {
s = s.replace("%kills%", String.valueOf(stats.getStat("kills", username)));
}
if (s.contains("%deaths%")) {
s = s.replace("%deaths%", String.valueOf(stats.getStat("deaths", username)));
}
if (s.contains("%kit%")) {
if (getKits().getKitOfPlayer(username) != null) {
s = s.replace("%kit%", getKits().getKitOfPlayer(username).getName());
} else {
s = s.replace("%kit%", "None");
}
}
return s;
}
public String generateRandomArenaSpawn(String arenaName) {
@@ -265,30 +186,17 @@ public class Arena {
return spawnKeys.get(random.nextInt(spawnKeys.size()));
}
public boolean isCombatActionPermittedInRegion(Player p) {
if (plugin.hasWorldGuard()) {
if (WorldGuardAPI.getInstance().allows(p, WorldGuardFlag.PVP.getFlag())) {
return true;
}
p.sendMessage(resources.getMessages().getString("Messages.Error.PVP"));
return false;
}
return true;
}
public Map<String, String> getHitCache() { return hitCache; }
public Stats getStats() { return stats; }
public Utilities getUtilities() { return utilties; }
public Leaderboards getLeaderboards() { return leaderboards; }
public Kits getKits() { return kits; }
public Abilities getAbilities() { return abilities; }
public KillStreaks getKillStreaks() { return killstreaks; }
@@ -1,20 +1,19 @@
package com.planetgallium.kitpvp.game;
import java.util.UUID;
import com.planetgallium.kitpvp.Game;
import com.planetgallium.kitpvp.api.Ability;
import com.planetgallium.kitpvp.api.Kit;
import com.planetgallium.kitpvp.util.CacheManager;
import com.planetgallium.kitpvp.util.Cooldown;
import com.zp4rker.localdb.DataType;
import org.bukkit.entity.Player;
public class Cooldowns {
private Infobase database;
private final Stats stats;
private final Infobase database;
public Cooldowns(Game plugin) {
public Cooldowns(Game plugin, Arena arena) {
this.stats = arena.getStats();
this.database = plugin.getDatabase();
}
@@ -23,11 +22,11 @@ public class Cooldowns {
}
public void setKitCooldown(String username, String kitName) {
database.setData(kitName + "_cooldowns", "last_used", (System.currentTimeMillis() / 1000), DataType.INTEGER, username);
long timeKitLastUsed = System.currentTimeMillis() / 1000;
stats.getOrCreateStatsCache(username).addKitCooldown(kitName, timeKitLastUsed);
}
public Cooldown getRemainingCooldown(Player p, Object type) {
long currentTimeSeconds = (System.currentTimeMillis() / 1000);
int timeLastUsedSeconds = 0;
int actionCooldownSeconds = 0;
@@ -60,7 +59,6 @@ public class Cooldowns {
int cooldownRemainingSeconds = (int) (timeLastUsedSeconds + actionCooldownSeconds - currentTimeSeconds);
return new Cooldown(cooldownRemainingSeconds);
}
}
@@ -1,269 +1,304 @@
package com.planetgallium.kitpvp.game;
import com.planetgallium.database.*;
import com.planetgallium.database.Record;
import com.planetgallium.kitpvp.Game;
import com.planetgallium.kitpvp.util.*;
import com.zp4rker.localdb.Column;
import com.zp4rker.localdb.DataType;
import com.zp4rker.localdb.Database;
import com.zp4rker.localdb.Table;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import java.io.File;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class Infobase {
private final Game plugin;
private final Resources resources;
private final Database database;
private final Map<String, Table> kitCooldownTables;
// TODO: implement database plan as specified via email
// TODO: make as generic as possible to make it applicable to other projects even ones unrelated to minecraft
// TODO: add caching for cooldowns
private final Database database;
private final Table statsTable;
private final static int UUID_MAX_CHARACTERS = 36;
private final static int USERNAME_MAX_CHARACTERS = 16;
public Infobase(Game plugin) {
this.plugin = plugin;
this.resources = plugin.getResources();
this.kitCooldownTables = new HashMap<>();
Column uuid = new Column("uuid", DataType.STRING, 0);
this.database = setupDatabase(resources.getConfig());
// Stats
Column username = new Column("username", DataType.STRING, 0);
Column kills = new Column("kills", DataType.INTEGER, 0);
Column deaths = new Column("deaths", DataType.INTEGER, 0);
Column experience = new Column("experience", DataType.INTEGER, 0);
Column level = new Column("level", DataType.INTEGER, 0);
Table statsTable = new Table("stats", uuid, username, kills, deaths, experience, level);
this.statsTable = database.createTable("stats", new Record(
new Field("uuid", DataType.FIXED_STRING, Infobase.UUID_MAX_CHARACTERS),
new Field("username", DataType.STRING, Infobase.USERNAME_MAX_CHARACTERS),
new Field("kills", DataType.INTEGER),
new Field("deaths", DataType.INTEGER),
new Field("experience", DataType.INTEGER),
new Field("level", DataType.INTEGER)));
// Cooldowns
Column last_used = new Column("last_used", DataType.INTEGER, 0);
this.database = new Database(plugin, "storage", statsTable, "plugins/KitPvP");
for (String kitName : resources.getKitList(false)) {
kitCooldownTables.put(kitName, new Table(kitName + "_cooldowns", uuid, last_used));
}
for (String kitCooldownTableName : kitCooldownTables.keySet()) {
if (!kitCooldownTableName.startsWith(".")) { // ignore hidden files
database.addTable(kitCooldownTables.get(kitCooldownTableName));
// Kit Cooldowns
for (String kitName : resources.getPluginDirectoryFiles("kits", false)) {
if (!kitName.startsWith(".")) { // ignore hidden files
addKitCooldownTable(kitName);
}
}
}
public void createPlayerStats(Player p) {
private Database setupDatabase(Resource config) {
Toolkit.printToConsole("&7[&b&lKIT-PVP&7] Establishing database connection...");
if (databaseTableContainsPlayer("stats", p.getName())) {
// Set database to MySQL, or in any other case, SQLite
if (config.fetchString("Storage.Type").equalsIgnoreCase("mysql")) {
String host = config.fetchString("Storage.MySQL.Host");
int port = config.getInt("Storage.MySQL.Port");
String databaseName = config.fetchString("Storage.MySQL.Database");
String username = config.fetchString("Storage.MySQL.Username");
String password = config.fetchString("Storage.MySQL.Password");
return new Database(host, port, databaseName, username, password);
} else {
return new Database("plugins/KitPvP/storage.db");
}
}
public boolean isPlayerRegistered(String username) {
String uuid = usernameToUUID(username);
return tableContainsUUID("stats", uuid);
}
public void registerPlayerStats(Player p) {
if (!verifyTableExists("stats")) {
return;
}
Column uuid = new Column("uuid", DataType.STRING, 0);
Column username = new Column("username", DataType.STRING, 0);
Column kills = new Column("kills", DataType.INTEGER, 0);
Column deaths = new Column("deaths", DataType.INTEGER, 0);
Column experience = new Column("experience", DataType.INTEGER, 0);
Column level = new Column("level", DataType.INTEGER, 0);
Field uuidField = uuidField("uuid", p.getUniqueId().toString());
Record playerRecord = statsTable.getRecord(uuidField);
uuid.setValue(p.getUniqueId().toString());
username.setValue(p.getName());
kills.setValue(0);
deaths.setValue(0);
experience.setValue(0);
level.setValue(resources.getLevels().getInt("Levels.Options.Minimum-Level"));
if (playerRecord == null) {
Record statsRecord = new Record(
uuidField,
new Field("username", DataType.STRING, p.getName(), Infobase.USERNAME_MAX_CHARACTERS),
new Field("kills", DataType.INTEGER, 0),
new Field("deaths", DataType.INTEGER, 0),
new Field("experience", DataType.INTEGER, 0),
new Field("level", DataType.INTEGER,
resources.getLevels().getInt("Levels.Options.Minimum-Level")));
statsTable.insertRecord(statsRecord);
} else {
// check if stored username needs changing if a player changed their username
String storedUsername = (String) playerRecord.getFieldValue("username");
String currentUsername = p.getName();
getTableByName("stats").insert(uuid, username, kills, deaths, experience, level);
if (!storedUsername.equals(currentUsername)) {
Field updatedUsernameField = new Field("username", DataType.STRING, p.getName(),
Infobase.USERNAME_MAX_CHARACTERS);
statsTable.updateRecord(uuidField, updatedUsernameField);
}
}
// put stats into stats cache
playerRecord = statsTable.getRecord(uuidField("uuid", p.getUniqueId().toString()));
CacheManager.getStatsCache().put(p.getName(), recordToPlayerData(playerRecord));
}
public void exportStats() {
Resource statsResource = new Resource(plugin, "stats.yml");
statsResource.load();
ConfigurationSection statsSection = statsResource.getConfigurationSection("Stats.Players");
Column uuidColumn = new Column("uuid", DataType.STRING);
Column username = new Column("username", DataType.STRING);
Column kills = new Column("kills", DataType.INTEGER);
Column deaths = new Column("deaths", DataType.INTEGER);
Column experience = new Column("experience", DataType.INTEGER);
Column level = new Column("level", DataType.INTEGER);
Table statsTable = getTableByName("stats");
for (String uuid : statsSection.getKeys(false)) {
ConfigurationSection playerSection = statsSection.getConfigurationSection(uuid);
uuidColumn.setValue(uuid);
username.setValue(playerSection.getString("Username"));
kills.setValue(playerSection.getInt("Kills"));
deaths.setValue(playerSection.getInt("Deaths"));
experience.setValue(playerSection.getInt("Experience"));
level.setValue(playerSection.getInt("Level"));
if (statsTable.containsColumn(uuidColumn)) {
statsTable.update(uuidColumn, username, kills, deaths, experience, level);
} else {
statsTable.insert(uuidColumn, username, kills, deaths, experience, level);
}
Field uuidField = uuidField("uuid", uuid);
Field usernameField = new Field("username", DataType.STRING,
playerSection.getString("Username"), Infobase.USERNAME_MAX_CHARACTERS);
Field killsField = new Field("kills", DataType.INTEGER, playerSection.getInt("Kills"));
Field deathsField = new Field("deaths", DataType.INTEGER, playerSection.getInt("Deaths"));
Field experienceField =
new Field("experience", DataType.INTEGER, playerSection.getInt("Experience"));
Field levelField = new Field("level", DataType.INTEGER, playerSection.getInt("Level"));
Record playerStatsRecord = new Record(uuidField, usernameField, killsField, deathsField, experienceField,
levelField);
statsTable.updateOrInsertRecord(playerStatsRecord);
}
File renamedStatsFile = new File("old_stats.yml");
if (!statsResource.getFile().renameTo(renamedStatsFile)) {
Toolkit.printToConsole("&7[&b&lKIT-PVP&7] &cThere was a problem renaming stats.yml to old_stats.yml.");
}
}
public void addKitCooldownTable(String kitName) {
Column uuid = new Column("uuid", DataType.STRING, 0);
Column last_used = new Column("last_used", DataType.INTEGER, 0);
kitCooldownTables.put(kitName, new Table(kitName + "_cooldowns", uuid, last_used));
database.addTable(kitCooldownTables.get(kitName));
}
public void deleteKitCooldownTable(String kitName) {
Table table = getTableByName(kitName + "_cooldowns");
if (table == null) return;
database.deleteTable(table);
cleanupUnusedKitCooldownTables();
}
public boolean databaseTableContainsPlayer(String tableName, String username) {
Table table = getTableByName(tableName);
if (table == null) return false;
String uuid = usernameToUUID(username);
Column uuidColumn = new Column("uuid", DataType.STRING, 0);
uuidColumn.setValue(uuid);
return table.containsColumn(uuidColumn);
}
public String usernameToUUID(String username) {
if (CacheManager.getUUIDCache().containsKey(username)) {
return CacheManager.getUUIDCache().get(username);
}
Table table = getTableByName("stats");
if (table == null) return null;
if (verifyTableExists("stats")) {
Table stats = database.getTable("stats");
Column usernameColumn = new Column("username", DataType.STRING);
usernameColumn.setValue(username);
List<Record> matchingRecords = stats.searchRecords(usernameField(username));
if (matchingRecords.size() == 1) {
Record matchingRecord = matchingRecords.get(0);
List<List<Column>> results = table.search(usernameColumn);
if (results.size() > 0 && results.get(0).size() > 0) {
String uuid = (String) table.search(usernameColumn).get(0).get(0).getValue();
CacheManager.getUUIDCache().put(username, uuid);
return uuid;
String uuid = (String) matchingRecord.getFieldValue("uuid");
CacheManager.getUUIDCache().put(username, uuid);
return uuid;
}
}
return null;
}
private boolean tableContainsUUID(String tableName, String uuid) {
if (verifyTableExists(tableName)) {
Table table = database.getTable(tableName);
return table.getRecord(uuidField("uuid", uuid)) != null;
}
return false;
}
public List<TopEntry> getTopNStats(String identifier, int n) {
if (verifyTableExists("stats")) {
Table table = database.getTable("stats");
return table.getTopN(new Field(identifier, DataType.INTEGER),
new Field("username", DataType.FIXED_STRING, Infobase.USERNAME_MAX_CHARACTERS), n);
}
return new ArrayList<>();
}
public void addKitCooldownTable(String kitName) {
database.createTable(kitName + "_cooldowns", new Record(
new Field("uuid", DataType.FIXED_STRING, Infobase.UUID_MAX_CHARACTERS),
new Field("last_used", DataType.INTEGER)));
}
public void deleteKitCooldownTable(String kitName) {
String kitCooldownTableName = kitName + "_cooldowns";
if (verifyTableExists(kitCooldownTableName)) {
database.deleteTable(kitCooldownTableName);
}
cleanupUnusedKitCooldownTables();
}
public void cleanupUnusedKitCooldownTables() {
for (Table table : database.getTables()) {
String tableName = table.getName();
for (String tableName : database.getTables().keySet()) {
if (tableName.contains("_cooldowns")) {
String kitName = tableName.split("_cooldowns")[0];
if (!plugin.getArena().getKits().isKit(kitName)) {
database.deleteTable(table);
database.deleteTable(tableName);
}
}
}
}
public List<PlayerEntry> getTopNStats(String identifier, int n) {
Column usernameColumn = new Column("username", DataType.STRING);
Column numberColumn = new Column(identifier, DataType.INTEGER);
return getTableByName("stats").getTopN(numberColumn, usernameColumn, n);
}
public Table getTableByName(String name) {
for (Table table : database.getTables()) {
if (table.getName().equals(name)) {
return table;
}
}
Toolkit.printToConsole(String.format("&7[&b&lKIT-PVP&7] &cCould not find table with name [%s]", name));
return null;
}
public List<Column> getRowByUUID(String tableName, String uuid) {
Table table = getTableByName(tableName);
if (table == null) return null;
Column uuidColumn = new Column("uuid", DataType.STRING, 0);
uuidColumn.setValue(uuid);
if (table.containsColumn(uuidColumn)) {
return table.getExact(uuidColumn);
}
return null;
}
public Column getColumnByName(String tableName, String columnName, String uuid) {
Table table = getTableByName(tableName);
if (table == null) return null;
for (Column column : getRowByUUID(tableName, uuid)) {
if (column.getName().equals(columnName)) {
return column;
}
}
return null;
}
public void setData(String tableName, String identifier, Object data, DataType type, String username) {
if (verifyTableExists(tableName)) {
Table table = database.getTable(tableName);
Table table = getTableByName(tableName);
if (table == null) return;
Field uuidField = uuidField("username", username);
Record record = table.getRecord(uuidField);
Field fieldToUpdate = new Field(identifier, type, data);
String uuid = usernameToUUID(username);
if (record != null) {
table.updateRecord(uuidField, fieldToUpdate);
} else {
System.out.printf("[Database] Failed to set data; database does not contain player %s\n", username);
}
}
}
Column dataColumn = new Column(identifier.toLowerCase(), type, 0);
dataColumn.setValue(data);
public void setStatsData(String username, PlayerData playerData) {
if (verifyTableExists("stats")) {
Table statsTable = database.getTable("stats");
Field uuidField = uuidField("username", username);
Column uuidColumn = new Column("uuid", DataType.STRING, 0);
uuidColumn.setValue(uuid);
List<Field> fieldsToUpdate = new ArrayList<>();
for (String statIdentifier : playerData.getData().keySet()) {
Field statField = new Field(statIdentifier, DataType.INTEGER, playerData.getData(statIdentifier));
fieldsToUpdate.add(statField);
}
if (databaseTableContainsPlayer(tableName, username)) {
table.update(uuidColumn, dataColumn);
} else {
table.insert(uuidColumn, dataColumn);
// by doing this, it updates a whole stat row with one single SQL statement
statsTable.updateRecord(uuidField, fieldsToUpdate.toArray(new Field[0]));
}
// Cooldowns
if (playerData.getKitCooldowns().size() > 0) {
for (Map.Entry<String, Long> entry : playerData.getKitCooldowns().entrySet()) {
String kitNameWithCooldown = entry.getKey();
long timeKitLastUsed = entry.getValue();
String kitCooldownTableName = "{kit_name}_cooldowns"
.replace("{kit_name}", kitNameWithCooldown);
if (verifyTableExists(kitCooldownTableName)) {
Table kitCooldownTable = database.getTable(kitCooldownTableName);
Record cooldownRecord = new Record(uuidField("username", username),
new Field("last_used", DataType.INTEGER, timeKitLastUsed));
kitCooldownTable.updateOrInsertRecord(cooldownRecord);
}
}
}
}
public Object getData(String tableName, String identifier, String username) {
if (verifyTableExists(tableName)) {
Table table = database.getTable(tableName);
Record record = table.getRecord(uuidField("username", username));
String uuid = usernameToUUID(username);
if (databaseTableContainsPlayer(tableName, username)) {
return getColumnByName(tableName, identifier, uuid).getValue();
if (record != null) {
return record.getFieldValue(identifier);
} /*else { // currently commented out because not being in a kit cooldown table prints this
System.out.printf("[Database] Failed to get data; database does not contain player %s\n", username);
} */
}
return null;
}
public PlayerData recordToPlayerData(Record playerRecord) {
PlayerData playerData = new PlayerData(-1, -1, -1, -1);
for (String statIdentifier : playerData.getData().keySet()) {
playerData.setData(statIdentifier, (int) playerRecord.getFieldValue(statIdentifier));
}
return playerData;
}
public PlayerData getStatsData(String username) {
PlayerData playerData = new PlayerData(-1, -1, -1, -1);
if (verifyTableExists("stats")) {
Table statsTable = database.getTable("stats");
Record playerRecord = statsTable.getRecord(uuidField("username", username));
return recordToPlayerData(playerRecord);
}
return playerData;
}
private boolean verifyTableExists(String tableName) {
if (database.getTable(tableName) != null) {
return true;
}
System.out.printf("[Database] Failed to perform action; table %s does not exist\n", tableName);
return false;
}
private Field uuidField(String flag, String value) {
if (flag.equalsIgnoreCase("username")) {
return new Field("uuid", DataType.FIXED_STRING, usernameToUUID(value),
Infobase.UUID_MAX_CHARACTERS);
} else if (flag.equalsIgnoreCase("uuid")) {
return new Field("uuid", DataType.FIXED_STRING, value,
Infobase.UUID_MAX_CHARACTERS);
}
return null;
}
private Field usernameField(String value) {
return new Field("username", DataType.STRING, value, Infobase.USERNAME_MAX_CHARACTERS);
}
}
@@ -2,9 +2,9 @@ package com.planetgallium.kitpvp.game;
import java.util.HashMap;
import com.cryptomorin.xseries.XSound;
import com.cryptomorin.xseries.messages.Titles;
import com.planetgallium.kitpvp.util.*;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -15,103 +15,100 @@ import org.bukkit.event.player.PlayerQuitEvent;
public class KillStreaks implements Listener {
private Resources resources;
private Resource killConfig;
private HashMap<String, Integer> kills = new HashMap<String, Integer>();
private final Resources resources;
private final Resource killConfig;
private final HashMap<String, Integer> kills;
public KillStreaks(Resources resources) {
this.resources = resources;
this.killConfig = resources.getKillStreaks();
this.kills = new HashMap<>();
}
@EventHandler
public void onKill(PlayerDeathEvent e) {
if (Toolkit.inArena(e.getEntity())) {
Player damager = e.getEntity().getKiller();
Player damagedPlayer = e.getEntity();
if (damager != null && damager.getName() != damagedPlayer.getName()) {
if (damager != null && !damager.getName().equals(damagedPlayer.getName())) {
kills.put(damager.getName(), getStreak(damager.getName()) + 1);
runCase("KillStreaks", getStreak(damager.getName()), damager.getName(), damager.getWorld(), damager);
runCase("EndStreaks", getStreak(damagedPlayer.getName()), damagedPlayer.getName(), damagedPlayer.getWorld(), damagedPlayer);
runStreakCase("KillStreaks", damager);
runStreakCase("EndStreaks", damagedPlayer);
kills.put(damagedPlayer.getName(), 0);
} else {
kills.put(damagedPlayer.getName(), 0);
runCase("EndStreaks", getStreak(damagedPlayer.getName()), damagedPlayer.getName(), damagedPlayer.getWorld(), damagedPlayer);
runStreakCase("EndStreaks", damagedPlayer);
}
}
}
@EventHandler
public void createStreak(PlayerJoinEvent e) {
Player p = e.getPlayer();
if (!kills.containsKey(p.getName())) {
kills.put(e.getPlayer().getName(), 0);
}
}
@EventHandler
public void removeStreak(PlayerQuitEvent e) {
if (resources.getConfig().getBoolean("Arena.ResetKillStreakOnLeave")) {
kills.put(e.getPlayer().getName(), 0);
}
}
public void runCase(String streakType, int streakNumber, String username, World world, Player p) {
public void runStreakCase(String streakType, Player p) {
String username = p.getName();
int streakNumber = getStreak(username);
World world = p.getWorld();
String pathPrefix = streakType + "." + streakNumber;
if (killConfig.contains(pathPrefix)) {
// TITLE
if (killConfig.contains(pathPrefix + ".Title")) {
String title = killConfig.fetchString(pathPrefix + ".Title.Title")
.replace("%player%", username)
.replace("%streak%", String.valueOf(streakNumber));
String subtitle = killConfig.fetchString(pathPrefix + ".Title.Subtitle")
.replace("%player%", username)
.replace("%streak%", String.valueOf(streakNumber));
for (Player local : world.getPlayers()) {
Titles.sendTitle(local, 20, 60, 20,
killConfig.getString(pathPrefix + ".Title.Title").replace("%player%", username).replace("%streak%", String.valueOf(streakNumber)),
killConfig.getString(pathPrefix + ".Title.Subtitle").replace("%player%", username).replace("%streak%", String.valueOf(streakNumber)));
Titles.sendTitle(local, 20, 60, 20, title, subtitle);
}
}
// SOUND
if (killConfig.contains(pathPrefix + ".Sound")) {
Sound sound = Toolkit.safeSound(killConfig.fetchString(pathPrefix + ".Sound.Sound"));
int pitch = killConfig.getInt(pathPrefix + ".Sound.Pitch");
for (Player local : world.getPlayers()) {
local.playSound(local.getLocation(), XSound.matchXSound(killConfig.getString(pathPrefix + ".Sound.Sound")).get().parseSound(), 1, killConfig.getInt(pathPrefix + ".Sound.Pitch"));
local.playSound(local.getLocation(), sound, 1, pitch);
}
}
// MESSAGE
if (killConfig.contains(pathPrefix + ".Message")) {
String message = killConfig.fetchString(pathPrefix + ".Message.Message")
.replace("%streak%", String.valueOf(streakNumber))
.replace("%player%", username);
for (Player local : world.getPlayers()) {
local.sendMessage(killConfig.getString(pathPrefix + ".Message.Message").replace("%streak%", String.valueOf(streakNumber)).replace("%player%", username));
local.sendMessage(message);
}
}
// COMMANDS
if (killConfig.contains(pathPrefix + ".Commands")) {
Toolkit.runCommands(p, killConfig.getStringList(pathPrefix + ".Commands"), "none", "none");
Toolkit.runCommands(p, killConfig.getStringList(pathPrefix + ".Commands"),
"none", "none");
}
}
@@ -119,28 +116,22 @@ public class KillStreaks implements Listener {
}
public int getStreak(String username) {
if (!kills.containsKey(username)) {
kills.put(username, 0);
}
return kills.get(username);
}
public void resetStreak(Player p) {
if (kills.containsKey(p.getName())) {
runCase("EndStreaks", getStreak(p.getName()), p.getName(), p.getWorld(), p);
runStreakCase("EndStreaks", p);
kills.put(p.getName(), 0);
}
}
public void setStreak(Player p, int streak) {
kills.put(p.getName(), streak);
}
}
@@ -9,7 +9,6 @@ import com.planetgallium.kitpvp.api.Kit;
import com.planetgallium.kitpvp.api.PlayerSelectKitEvent;
import com.planetgallium.kitpvp.item.AttributeParser;
import com.planetgallium.kitpvp.util.*;
import com.zp4rker.localdb.Table;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@@ -17,7 +16,6 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
@@ -39,6 +37,9 @@ public class Kits {
this.kits = new HashMap<>();
}
// Could also load and cache kits onEnable like Abilities.yml so no lag spike for hefty kit when first used by
// player
public void createKit(Player fromPlayer, String kitName) {
Kit kitToCreate = createKitFromPlayer(fromPlayer, kitName);
@@ -72,9 +73,9 @@ public class Kits {
menuConfig.save();
menuConfig.load();
arena.getMenus().getKitMenu().clearCache();
arena.getMenus().getKitMenu().rebuildCache();
} else {
fromPlayer.sendMessage(messages.getString("Messages.Error.Menu"));
fromPlayer.sendMessage(messages.fetchString("Messages.Error.Menu"));
}
}
@@ -82,7 +83,6 @@ public class Kits {
}
public Kit createKitFromPlayer(Player player, String name) {
Player p = player;
// KIT //
@@ -111,7 +111,7 @@ public class Kits {
if (item != null) {
if (item.getType() == XMaterial.MUSHROOM_STEW.parseMaterial()) {
ItemMeta itemMeta = item.getItemMeta();
itemMeta.setDisplayName(resources.getConfig().getString("Soups.Name"));
itemMeta.setDisplayName(resources.getConfig().fetchString("Soups.Name"));
itemMeta.setLore(Toolkit.colorizeList(resources.getConfig().getStringList("Soups.Lore")));
item.setItemMeta(itemMeta);
}
@@ -128,35 +128,34 @@ public class Kits {
// ABILITY //
Ability sampleAbility = new Ability("Example");
Ability sampleAbility = new Ability(kit.getName() + "-Blank");
ItemStack activator = XMaterial.EMERALD.parseItem();
ItemMeta activatorMeta = activator.getItemMeta();
activatorMeta.setDisplayName(Toolkit.translate("&aDefault Ability &7(Must be modified in kit file)"));
activatorMeta.setDisplayName(Toolkit.translate("&aBlank Kit Ability &7(Right Click)"));
activator.setItemMeta(activatorMeta);
sampleAbility.setActivator(activator);
sampleAbility.setMessage("%prefix% &7You have used your ability.");
sampleAbility.setSound(XSound.BLOCK_NOTE_BLOCK_PLING.parseSound(), 1, 1);
sampleAbility.addEffect(XPotion.SPEED.parsePotionEffectType(), 1, 10);
sampleAbility.addEffect(XPotion.SPEED.getPotionEffectType(), 1, 10);
sampleAbility.addCommand("console: This command is run from the console, you can use %player%");
sampleAbility.addCommand("player: This command is run from the player, you can use %player%");
kit.addAbility(sampleAbility);
resources.addAbilityResource(sampleAbility);
return kit;
}
private Kit createKitFromResource(Resource resource) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Kit kit = new Kit(trimName(resource.getName()));
kit.setPermission(resource.getString("Kit.Permission"));
kit.setPermission(resource.fetchString("Kit.Permission"));
kit.setLevel(resource.getInt("Kit.Level"));
kit.setCooldown(new Cooldown(resource.getString("Kit.Cooldown")));
kit.setCooldown(new Cooldown(resource.fetchString("Kit.Cooldown")));
kit.setHealth(resource.contains("Kit.Health") ? resource.getInt("Kit.Health") : 20);
@@ -178,7 +177,16 @@ public class Kits {
kit.setFill(AttributeParser.getItemStackFromPath(resource, "Inventory.Items.Fill"));
kit.setOffhand(AttributeParser.getItemStackFromPath(resource, "Inventory.Items.Offhand"));
AttributeParser.getAbilitiesFromResource(resource).forEach(ability -> kit.addAbility(ability));
kit.setOption("AddOverflowItemsOnKit",
resources.getConfig().getBoolean("Arena.AddOverflowItemsOnKit"));
kit.setOption("DropRemainingOverflowItemsOnKit",
resources.getConfig().getBoolean("Arena.DropRemainingOverflowItemsOnKit"));
kit.setOption("Message-OverflowItemsLost",
resources.getMessages().fetchString("Messages.Error.OverflowItemsLost"));
kit.setOption("Message-OverflowItemsDropped",
resources.getMessages().fetchString("Messages.Other.OverflowItemsDropped"));
// AttributeParser.getAbilitiesFromResource(resource).forEach(ability -> kit.addAbility(ability));
return kit;
@@ -189,29 +197,29 @@ public class Kits {
Player p = player;
if (kit == null) {
p.sendMessage(messages.getString("Messages.Error.Lost"));
p.sendMessage(messages.fetchString("Messages.Error.Lost"));
return;
}
if (!p.hasPermission(kit.getPermission())) {
p.sendMessage(messages.getString("Messages.General.Permission").replace("%permission%", kit.getPermission()));
p.sendMessage(messages.fetchString("Messages.General.Permission").replace("%permission%", kit.getPermission()));
return;
}
if (!(Toolkit.getPermissionAmount(p, "kp.levelbypass.", 0) >= kit.getLevel() ||
arena.getStats().getStat("level", p.getName()) >= kit.getLevel())) {
p.sendMessage(messages.getString("Messages.Other.Needed").replace("%level%", String.valueOf(kit.getLevel())));
p.sendMessage(messages.fetchString("Messages.Other.Needed").replace("%level%", String.valueOf(kit.getLevel())));
return;
}
Cooldown cooldownRemaining = arena.getCooldowns().getRemainingCooldown(p, kit);
if (!p.hasPermission("kp.cooldownbypass") && cooldownRemaining.toSeconds() > 0) {
p.sendMessage(messages.getString("Messages.Error.CooldownKit").replace("%cooldown%", cooldownRemaining.formatted(false)));
p.sendMessage(messages.fetchString("Messages.Error.CooldownKit").replace("%cooldown%", cooldownRemaining.formatted(false)));
return;
}
if (hasKit(player.getName())) {
p.sendMessage(messages.getString("Messages.Error.Selected"));
p.sendMessage(messages.fetchString("Messages.Error.Selected"));
p.playSound(p.getLocation(), XSound.ENTITY_ENDER_DRAGON_HURT.parseSound(), 1, 1);
return;
}
@@ -222,7 +230,7 @@ public class Kits {
}
kit.apply(p);
p.sendMessage(messages.getString("Messages.Commands.Kit").replace("%kit%", kit.getName()));
p.sendMessage(messages.fetchString("Messages.Commands.Kit").replace("%kit%", kit.getName()));
p.playSound(p.getLocation(), XSound.ENTITY_HORSE_ARMOR.parseSound(), 1, 1);
Bukkit.getPluginManager().callEvent(new PlayerSelectKitEvent(player, kit));
@@ -242,16 +250,12 @@ public class Kits {
}
public void deleteKit(String kitName) {
resources.removeResource(kitName + ".yml");
plugin.getDatabase().deleteKitCooldownTable(kitName);
}
public Kit getKitByName(String kitName) {
return loadKitFromCacheOrCreate(kitName);
}
private String trimName(String kitNameWithFileEnding) {
@@ -272,20 +276,18 @@ public class Kits {
}
public Kit getKitOfPlayer(String playerName) {
String kitName = kits.get(playerName);
if (kitName == null) {
return null;
}
return loadKitFromCacheOrCreate(kitName);
}
private Kit loadKitFromCacheOrCreate(String kitName) {
if (!CacheManager.getKitCache().containsKey(kitName)) {
if (resources.getKitList(false).contains(kitName)) {
if (resources.getPluginDirectoryFiles("kits", false).contains(kitName)) {
Resource kit = resources.getKit(kitName);
try {
CacheManager.getKitCache().put(kitName, createKitFromResource(kit));
@@ -309,7 +311,7 @@ public class Kits {
public boolean isKit(String kitName) {
return resources.getKitList(false).contains(kitName);
return resources.getPluginDirectoryFiles("kits", false).contains(kitName);
}
@@ -0,0 +1,72 @@
package com.planetgallium.kitpvp.game;
import com.planetgallium.database.TopEntry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Leaderboard {
private final String name;
private final List<TopEntry> rankings;
private final int maxSize;
public Leaderboard(String name, List<TopEntry> initialRankings, int maxSize) {
this.name = name;
this.rankings = initialRankings;
this.maxSize = maxSize;
}
public void updateRankings(TopEntry playerEntry) {
if (rankings.size() < maxSize) {
rankings.add(playerEntry);
sortRankings();
} else if (rankings.size() == maxSize) {
TopEntry lowestRankingPlayer = rankings.get(rankings.size() - 1);
if (playerEntry.getValue() > lowestRankingPlayer.getValue()) {
if (!rankingsContainPlayer(playerEntry.getIdentifier())) {
// remove lowest ranking player and add new better player
rankings.remove(rankings.size() - 1);
rankings.add(playerEntry);
} else {
// update ranking for player already in leaderboard
updatePlayerEntryInRanking(playerEntry);
}
sortRankings(); // resort in both above cases
}
}
}
public TopEntry getNRanking(int n) { // n = 1 is top player
if (n <= rankings.size() && n >= 1) {
return rankings.get(n - 1);
}
return new TopEntry("N / A", 0);
}
private boolean rankingsContainPlayer(String username) {
for (TopEntry entry : this.rankings) {
if (entry.getIdentifier().equals(username)) {
return true;
}
}
return false;
}
private void updatePlayerEntryInRanking(TopEntry updatedEntry) {
for (TopEntry entry : this.rankings) {
if (entry.getIdentifier().equals(updatedEntry.getIdentifier())) {
entry.setValue(updatedEntry.getValue());
return;
}
}
}
public void sortRankings() {
Collections.sort(rankings);
}
public String getName() { return name; }
}
@@ -1,134 +1,42 @@
package com.planetgallium.kitpvp.game;
import com.planetgallium.database.TopEntry;
import com.planetgallium.kitpvp.Game;
import com.planetgallium.kitpvp.util.PlayerEntry;
import com.planetgallium.kitpvp.util.Toolkit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Leaderboards {
private final Infobase database;
private final Map<String, List<PlayerEntry>> leaderboards;
private final Map<String, Leaderboard> leaderboards;
public Leaderboards(Game plugin) {
this.database = plugin.getDatabase();
Infobase database = plugin.getDatabase();
this.leaderboards = new HashMap<>();
Toolkit.printToConsole("&7[&b&lKIT-PVP&7] &7Loading Leaderboard caches....");
registerCache("kills", 25);
registerCache("deaths", 25);
registerCache("level", 25);
// TODO: implement PriorityQueue to manage cached Leaderboards... currently you're basically recreating it lol...
leaderboards.put("kills",
new Leaderboard("kills", database.getTopNStats("kills", 25), 25));
leaderboards.put("deaths",
new Leaderboard("kills", database.getTopNStats("deaths", 25), 25));
leaderboards.put("level",
new Leaderboard("kills", database.getTopNStats("level", 25), 25));
}
private void registerCache(String key, int size) {
leaderboards.put(key, new ArrayList<>());
leaderboards.get(key).addAll(database.getTopNStats(key, size));
}
public void updateCache(String key, PlayerEntry playerEntry) {
if (!isValidCacheType(key)) return;
List<PlayerEntry> leaderboard = getLeaderboard(key);
if (leaderboard.size() == 0) {
return;
public void updateRankings(String leaderboardName, TopEntry newEntry) {
if (isValidLeaderboardName(leaderboardName)) {
leaderboards.get(leaderboardName).updateRankings(newEntry);
}
PlayerEntry lowestRankingPlayer = leaderboard.get(leaderboard.size() - 1);
}
// If updated player entry has a higher data value than the lowest ranking player in a leaderboard
if (playerEntry.getData() > lowestRankingPlayer.getData()) {
if (!cacheContainsPlayer(leaderboard, playerEntry.getUsername())) {
// If not already in the leaderboard, add them
leaderboard.add(playerEntry);
} else {
// If already in the leaderboard, update their player entry with the latest data
updatePlayerEntry(leaderboard, playerEntry);
}
// Sort the leaderboard based on the new insertion / data
insertionSort(leaderboard);
} else {
// If updated player entry does not have a higher data value than the lowest ranking player in the leaderboard
if (cacheContainsPlayer(leaderboard, playerEntry.getUsername())) {
// If they are in the leaderboard, remove them and resort
removePlayerFromCache(leaderboard, playerEntry.getUsername());
insertionSort(leaderboard); // idk if this sort is necessary
}
public TopEntry getTopN(String leaderboardName, int rank) {
if (isValidLeaderboardName(leaderboardName)) {
return leaderboards.get(leaderboardName).getNRanking(rank);
}
return new TopEntry("NAN", -1);
}
private boolean isValidCacheType(String identifier) {
return identifier.equals("kills") || identifier.equals("deaths") || identifier.equals("level");
}
private boolean cacheContainsPlayer(List<PlayerEntry> leaderboard, String username) {
for (PlayerEntry entry : leaderboard) {
if (entry.getUsername().equals(username)) {
return true;
}
}
return false;
}
private void updatePlayerEntry(List<PlayerEntry> leaderboard, PlayerEntry playerEntry) {
for (PlayerEntry entry : leaderboard) {
if (entry.getUsername().equals(playerEntry.getUsername())) {
entry.setData(playerEntry.getData());
break;
}
}
}
private void removePlayerFromCache(List<PlayerEntry> leaderboard, String username) {
for (PlayerEntry entry : leaderboard) {
if (entry.getUsername().equals(username)) {
leaderboard.remove(entry);
break;
}
}
}
private void insertionSort(List<PlayerEntry> leaderboard) {
for (int i = 1; i < leaderboard.size(); ++i) {
PlayerEntry currentEntry = leaderboard.get(i);
int j = i - 1;
while (j >= 0 && leaderboard.get(j).getData() < currentEntry.getData()) {
leaderboard.set(j + 1, leaderboard.get(j));
j -= 1;
}
leaderboard.set(j + 1, currentEntry);
}
}
public PlayerEntry getTopN(String key, int rank) {
List<PlayerEntry> leaderboard = getLeaderboard(key);
int rankIndex = rank - 1;
return rankIndex < leaderboard.size() ? leaderboard.get(rankIndex) : new PlayerEntry("N / A", 0);
}
private List<PlayerEntry> getLeaderboard(String key) {
return leaderboards.get(key);
private boolean isValidLeaderboardName(String leaderboardName) {
return leaderboardName.equals("kills") || leaderboardName.equals("deaths") || leaderboardName.equals("level");
}
}
@@ -1,23 +1,26 @@
package com.planetgallium.kitpvp.game;
import com.cryptomorin.xseries.XSound;
import com.planetgallium.database.TopEntry;
import com.planetgallium.kitpvp.Game;
import com.planetgallium.kitpvp.api.PlayerLevelUpEvent;
import com.planetgallium.kitpvp.util.*;
import com.zp4rker.localdb.DataType;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.List;
public class Stats {
private final Game plugin;
private final Infobase database;
private final Resources resources;
private final Resource levels;
private final Leaderboards leaderboards;
public Stats(Game plugin, Arena arena) {
this.plugin = plugin;
this.database = plugin.getDatabase();
this.resources = plugin.getResources();
this.levels = plugin.getResources().getLevels();
@@ -26,13 +29,14 @@ public class Stats {
public void createPlayer(Player p) {
CacheManager.getUUIDCache().put(p.getName(), p.getUniqueId().toString());
if (!isPlayerRegistered(p.getName())) {
database.createPlayerStats(p);
}
database.registerPlayerStats(p);
}
public boolean isPlayerRegistered(String username) {
return database.databaseTableContainsPlayer("stats", username);
private boolean isPlayerRegistered(String username) {
if (CacheManager.getStatsCache().containsKey(username)) { // try to use cache first to be faster
return true;
}
return database.isPlayerRegistered(username);
}
public double getKDRatio(String username) {
@@ -44,7 +48,7 @@ public class Stats {
}
public void removeExperience(String username, int amount) {
if (levels.getBoolean("Levels.Levels.Enabled") && isPlayerRegistered(username)) {
if (levels.getBoolean("Levels.Levels.Enabled")) {
int currentExperience = getStat("experience", username);
setStat("experience", username, currentExperience >= amount ? currentExperience - amount : 0);
}
@@ -68,7 +72,6 @@ public class Stats {
}
public void levelUp(Player p) {
String username = p.getName();
if (getStat("level", username) < levels.getInt("Levels.Options.Maximum-Level")) {
@@ -85,14 +88,13 @@ public class Stats {
Toolkit.runCommands(p, commandsList, "%level%", String.valueOf(newLevel));
}
p.sendMessage(resources.getMessages().getString("Messages.Other.Level")
p.sendMessage(resources.getMessages().fetchString("Messages.Other.Level")
.replace("%level%", String.valueOf(newLevel)));
XSound.play(p, "ENTITY_PLAYER_LEVELUP, 1, 1");
} else {
setStat("experience", username, 0);
}
}
public void addToStat(String identifier, String username, int amount) {
@@ -101,43 +103,56 @@ public class Stats {
}
public void setStat(String identifier, String username, int data) {
if (isPlayerRegistered(username)) {
PlayerData playerData = getOrCreateStatsCache(username);
playerData.setDataByIdentifier(identifier, data);
database.setData("stats", identifier, data, DataType.INTEGER, username);
leaderboards.updateCache(identifier, new PlayerEntry(username, data));
} else {
Toolkit.printToConsole(String.format("&7[&b&lKIT-PVP&7] &cFailed to set stats of player %s; not in database.", username));
if (!isPlayerRegistered(username)) {
return;
}
getOrCreateStatsCache(username).setData(identifier, data);
leaderboards.updateRankings(identifier, new TopEntry(username, data));
}
public void pushCachedStatsToDatabase(String username, boolean removeFromCacheAfter) {
new BukkitRunnable() {
@Override
public void run() {
if (!CacheManager.getStatsCache().containsKey(username)) {
return; // nothing to push if stats cache is empty
}
database.setStatsData(username, getOrCreateStatsCache(username));
if (removeFromCacheAfter) {
CacheManager.getStatsCache().remove(username);
}
}
}.runTaskAsynchronously(plugin);
}
public int getStat(String identifier, String username) {
return getOrCreateStatsCache(username).getDataByIdentifier(identifier);
if (!isPlayerRegistered(username)) {
return -1;
}
return getOrCreateStatsCache(username).getData(identifier);
}
private PlayerData getOrCreateStatsCache(String username) {
if (!CacheManager.getStatsCache().containsKey(username)) {
int kills = (int) database.getData("stats", "kills", username);
int deaths = (int) database.getData("stats", "deaths", username);
int experience = (int) database.getData("stats", "experience", username);
int level = (int) database.getData("stats", "level", username);
PlayerData playerData = new PlayerData(kills, deaths, experience, level);
public PlayerData getOrCreateStatsCache(String username) {
if (!isPlayerRegistered(username)) {
return new PlayerData(-1, -1, -1, -1);
}
CacheManager.getStatsCache().put(username, playerData);
if (!CacheManager.getStatsCache().containsKey(username)) {
CacheManager.getStatsCache().put(username, database.getStatsData(username));
}
return CacheManager.getStatsCache().get(username);
}
public int getRegularOrRelativeNeededExperience(String username) {
int level = getStat("level", username);
if (levels.contains("Levels.Levels." + level + ".Experience-To-Level-Up")) {
return levels.getInt("Levels.Levels." + level + ".Experience-To-Level-Up");
}
return levels.getInt("Levels.Options.Experience-To-Level-Up");
}
}
@@ -0,0 +1,107 @@
package com.planetgallium.kitpvp.game;
import com.planetgallium.kitpvp.Game;
import com.planetgallium.kitpvp.util.Resources;
import com.planetgallium.kitpvp.util.WorldGuardAPI;
import com.planetgallium.kitpvp.util.WorldGuardFlag;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.entity.Player;
public class Utilities {
private final Game plugin;
private final Arena arena;
private final Resources resources;
public Utilities(Game plugin, Arena arena) {
this.plugin = plugin;
this.arena = arena;
this.resources = plugin.getResources();
}
public String getPlayerLevelPrefix(String username) {
String playerLevel = String.valueOf(arena.getStats().getStat("level", username));
return resources.getLevels().fetchString("Levels.Levels." + playerLevel + ".Prefix")
.replace("%level%", playerLevel);
}
public String addPlaceholdersIfPossible(Player p, String text) {
if (plugin.hasPlaceholderAPI()) {
text = PlaceholderAPI.setPlaceholders(p, text);
}
return replaceBuiltInPlaceholdersIfPresent(text, p.getName());
}
public String replaceBuiltInPlaceholdersIfPresent(String s, String username) {
// The reason I'm doing all these if statements rather than a more concise code solution is to reduce
// the amount of data that is unnecessarily fetched (ex by using .replace) to improve performance
// no longer constantly fetching stats from database for EACH line of scoreboard on update and player join
if (s.contains("%streak%")) {
s = s.replace("%streak%", String.valueOf(arena.getKillStreaks().getStreak(username)));
}
if (s.contains("%player%")) {
s = s.replace("%player%", username);
}
if (s.contains("%xp%")) {
s = s.replace("%xp%", String.valueOf(arena.getStats().getStat("experience", username)));
}
if (s.contains("%level%")) {
s = s.replace("%level%", String.valueOf(arena.getStats().getStat("level", username)));
}
if (s.contains("%level_prefix%")) {
String levelPrefix = getPlayerLevelPrefix(username);
s = s.replace("%level_prefix%", levelPrefix);
}
if (s.contains("%max_xp%")) {
s = s.replace("%max_xp%", String.valueOf(arena.getStats().getRegularOrRelativeNeededExperience(username)));
}
if (s.contains("%max_level%")) {
s = s.replace("%max_level%",
String.valueOf(resources.getLevels().getInt("Levels.Options.Maximum-Level")));
}
if (s.contains("%kd%")) {
s = s.replace("%kd%", String.valueOf(arena.getStats().getKDRatio(username)));
}
if (s.contains("%kills%")) {
s = s.replace("%kills%", String.valueOf(arena.getStats().getStat("kills", username)));
}
if (s.contains("%deaths%")) {
s = s.replace("%deaths%", String.valueOf(arena.getStats().getStat("deaths", username)));
}
if (s.contains("%kit%")) {
if (arena.getKits().getKitOfPlayer(username) != null) {
s = s.replace("%kit%", arena.getKits().getKitOfPlayer(username).getName());
} else {
s = s.replace("%kit%", "None");
}
}
return s;
}
public boolean isCombatActionPermittedInRegion(Player p) {
if (plugin.hasWorldGuard()) {
if (WorldGuardAPI.getInstance().allows(p, WorldGuardFlag.PVP.getFlag())) {
return true;
}
p.sendMessage(resources.getMessages().fetchString("Messages.Error.PVP"));
return false;
}
return true;
}
}
@@ -41,7 +41,7 @@ public class AttributeParser {
if (effectsSection != null) {
for (String effectName : effectsSection.getKeys(false)) {
PotionEffectType type = XPotion.matchXPotion(effectName).get().parsePotionEffectType();
PotionEffectType type = XPotion.matchXPotion(effectName).get().getPotionEffectType();
int amplifier = resource.getInt(path + "." + effectName + ".Amplifier");
int duration = resource.getInt(path + "." + effectName + ".Duration");
@@ -56,69 +56,6 @@ public class AttributeParser {
}
public static List<Ability> getAbilitiesFromResource(Resource resource) {
List<Ability> abilities = new ArrayList<>();
ConfigurationSection abilitySection = resource.getConfigurationSection("Abilities");
if (abilitySection == null) return new ArrayList<>();
for (String abilityName : abilitySection.getKeys(false)) {
Ability ability = new Ability(abilityName);
String pathPrefix = "Abilities." + abilityName;
String activatorMaterial = resource.getString(pathPrefix + ".Activator.Material");
String activatorName = resource.getString(pathPrefix + ".Activator.Name");
ItemStack activator = new ItemStack(XMaterial.matchXMaterial(activatorMaterial).get().parseMaterial());
ItemMeta abilityMeta = activator.getItemMeta();
abilityMeta.setDisplayName(activatorName);
activator.setItemMeta(abilityMeta);
ability.setActivator(activator);
if (resource.contains(pathPrefix + ".Cooldown")) {
String formattedCooldown = resource.getString(pathPrefix + ".Cooldown.Cooldown");
ability.setCooldown(new Cooldown(formattedCooldown));
}
if (resource.contains(pathPrefix + ".Message")) {
String abilityMessage = resource.getString(pathPrefix + ".Message.Message");
ability.setMessage(abilityMessage);
}
if (resource.contains(pathPrefix + ".Sound")) {
Sound abilitySound = XSound.matchXSound(resource.getString(pathPrefix + ".Sound.Sound")).get().parseSound();
int abilitySoundPitch = resource.getInt(pathPrefix + ".Sound.Pitch");
int abilitySoundVolume = resource.getInt(pathPrefix + ".Sound.Volume");
ability.setSound(abilitySound, abilitySoundPitch, abilitySoundVolume);
}
if (resource.contains(pathPrefix + ".Effects")) {
ConfigurationSection effectSection = resource.getConfigurationSection(pathPrefix + ".Effects");
for (String effectName : effectSection.getKeys(false)) {
PotionEffectType effectType = XPotion.matchXPotion(effectName).get().parsePotionEffectType();
int amplifier = resource.getInt(pathPrefix + ".Effects." + effectName + ".Amplifier");
int duration = resource.getInt(pathPrefix + ".Effects." + effectName + ".Duration");
ability.addEffect(effectType, amplifier, duration);
}
}
if (resource.contains(pathPrefix + ".Commands")) {
for (String command : resource.getStringList(pathPrefix + ".Commands")) {
ability.addCommand(command);
}
}
abilities.add(ability);
}
return abilities;
}
public static ItemStack getItemStackFromPath(Resource resource, String path) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
if (!resource.contains(path)) return null;
@@ -129,7 +66,7 @@ public class AttributeParser {
// BASIC ITEM INFORMATION //
if (resource.contains(path + ".Name")) {
meta.setDisplayName(resource.getString(path + ".Name"));
meta.setDisplayName(resource.fetchString(path + ".Name"));
}
if (resource.contains(path + ".Lore")) {
@@ -137,7 +74,7 @@ public class AttributeParser {
}
if (resource.contains(path + ".Material")) {
String materialValue = resource.getString(path + ".Material");
String materialValue = resource.fetchString(path + ".Material");
Optional<XMaterial> possibleMaterial = XMaterial.matchXMaterial(materialValue);
if (possibleMaterial.isPresent()) {
@@ -171,7 +108,7 @@ public class AttributeParser {
}
if (resource.contains(path + ".Skull")) {
setSkull(item, resource.getString(path + ".Skull"));
setSkull(item, resource.fetchString(path + ".Skull"));
}
if (resource.contains(path + ".Durability")) {
@@ -186,7 +123,7 @@ public class AttributeParser {
Enchantment enchantment = FALLBACK_ITEM_ENCHANTMENT;
Optional<XEnchantment> enchantmentFromConfig = XEnchantment.matchXEnchantment(enchantmentName.toUpperCase());
if (enchantmentFromConfig.isPresent()) {
enchantment = enchantmentFromConfig.get().parseEnchantment();
enchantment = enchantmentFromConfig.get().getEnchant();
} else {
Toolkit.printToConsole(String.format("&7[&b&lKIT-PVP&7] &cUnknown enchantment [%s], defaulting to [THORNS].", enchantmentName));
}
@@ -308,7 +245,7 @@ public class AttributeParser {
boolean isExtended = resource.getBoolean(firstChildPath + ".Extended");
if (Toolkit.versionToNumber() == 18) {
boolean isSplash = resource.getString(path.replace("Effects", "") + ".Type").equals("SPLASH_POTION");
boolean isSplash = resource.fetchString(path.replace("Effects", "") + ".Type").equals("SPLASH_POTION");
Potion potion = Potion.fromItemStack(item);
potion.setSplash(isSplash);
potion.setType(potionType);
@@ -15,8 +15,8 @@ import com.planetgallium.kitpvp.util.Toolkit;
public class AbilityListener implements Listener {
private Arena arena;
private Resources resources;
private final Arena arena;
private final Resources resources;
public AbilityListener(Game plugin) {
this.arena = plugin.getArena();
@@ -25,25 +25,24 @@ public class AbilityListener implements Listener {
@EventHandler
public void onAbility(PlayerAbilityEvent e) {
Player p = e.getPlayer();
if (!arena.isCombatActionPermittedInRegion(p)) {
if (!arena.getUtilities().isCombatActionPermittedInRegion(p)) {
return;
}
Kit kit = arena.getKits().getKitOfPlayer(p.getName());
Ability ability = e.getAbility();
String abilityPermission = "kp.ability." + kit.getName().toLowerCase();
String abilityPermission = "kp.ability." + ability.getName().toLowerCase();
if (!p.hasPermission(abilityPermission)) {
p.sendMessage(resources.getMessages().getString("Messages.General.Permission").replace("%permission%", abilityPermission));
p.sendMessage(resources.getMessages().fetchString("Messages.General.Permission")
.replace("%permission%", abilityPermission));
return;
}
Cooldown cooldownRemaining = arena.getCooldowns().getRemainingCooldown(p, ability);
if (cooldownRemaining.toSeconds() > 0) {
p.sendMessage(resources.getMessages().getString("Messages.Error.CooldownAbility")
p.sendMessage(resources.getMessages().fetchString("Messages.Error.CooldownAbility")
.replace("%cooldown%", cooldownRemaining.formatted(false)));
return;
}
@@ -16,95 +16,78 @@ import com.planetgallium.kitpvp.util.Toolkit;
public class ArrowListener implements Listener {
private Resource config;
private final Game plugin;
private final Resource config;
public ArrowListener(Game plugin) {
this.plugin = plugin;
this.config = plugin.getResources().getConfig();
}
@EventHandler
public void onShot(EntityDamageByEntityEvent e) {
if (Toolkit.inArena(e.getEntity()) && config.getBoolean("Combat.ArrowHit.Enabled")) {
if (e.getEntity() instanceof Player && e.getDamager() instanceof Arrow) {
Player damagedPlayer = (Player) e.getEntity();
Arrow arrow = (Arrow) e.getDamager();
if (arrow.getShooter() != null && arrow.getShooter() instanceof Player) {
Player shooter = (Player) arrow.getShooter();
// ARROW HEALTH MESSAGE
if (damagedPlayer.getName() != shooter.getName()) {
new BukkitRunnable() {
@Override
public void run() {
double health = Math.round(damagedPlayer.getHealth() * 10.0) / 10.0;
if (shooter.hasPermission("kp.arrowmessage")) {
if (health != 20.0) {
shooter.sendMessage(config.getString("Combat.ArrowHit.Message").replace("%player%", damagedPlayer.getName()).replace("%health%", String.valueOf(health)));
}
}
}
}.runTaskLater(Game.getInstance(), 2L);
}
// ARROW RETURN
public void onArrowHit(EntityDamageByEntityEvent e) {
if (Toolkit.inArena(e.getEntity()) &&
e.getEntity() instanceof Player && e.getDamager() instanceof Arrow) {
Player damagedPlayer = (Player) e.getEntity();
Arrow arrow = (Arrow) e.getDamager();
ItemStack arrowToAdd = new ItemStack(Material.ARROW);
if (arrow.getShooter() != null && arrow.getShooter() instanceof Player) {
Player shooter = (Player) arrow.getShooter();
if (config.getBoolean("Combat.ArrowReturn.Enabled")) {
for (ItemStack items : shooter.getInventory().getContents()) {
if (items != null && items.getType() == XMaterial.ARROW.parseMaterial() && items.getAmount() < 64) {
if (shooter.hasPermission("kp.arrowreturn")) {
shooter.getInventory().addItem(arrowToAdd);
shooter.getInventory().addItem(arrowToAdd);
return;
}
}
}
if (shooter.getInventory().firstEmpty() == -1) {
shooter.sendMessage(config.getString("Combat.ArrowReturn.NoSpace"));
} else {
shooter.getInventory().addItem(arrowToAdd);
shooter.getInventory().addItem(arrowToAdd);
}
}
// make sure damaged player isn't shooter (self-hit)
if (!damagedPlayer.getName().equals(shooter.getName())) {
doArrowHitMessageIfEnabled(shooter, damagedPlayer);
doArrowReturnIfEnabled(shooter, damagedPlayer);
}
}
}
}
private void doArrowHitMessageIfEnabled(Player shooter, Player damagedPlayer) {
if (config.getBoolean("Combat.ArrowHit.Enabled")) {
new BukkitRunnable() {
@Override
public void run() {
double health = Math.round(damagedPlayer.getHealth() * 10.0) / 10.0;
if (shooter.hasPermission("kp.arrowmessage")) {
if (health != 20.0) {
shooter.sendMessage(config.fetchString("Combat.ArrowHit.Message").replace("%player%", damagedPlayer.getName()).replace("%health%", String.valueOf(health)));
}
}
}
}.runTaskLater(plugin, 2L);
}
}
private void doArrowReturnIfEnabled(Player shooter, Player damagedPlayer) {
if (config.getBoolean("Combat.ArrowReturn.Enabled")) {
// Do not do arrow return if damagedPlayer does not have a kit (if NoKitProtection is enabled)
if (config.getBoolean("Arena.NoKitProtection")) {
if (!plugin.getArena().getKits().hasKit(damagedPlayer.getName())) {
return;
}
}
ItemStack arrowToAdd = new ItemStack(Material.ARROW, config.getInt("Combat.ArrowReturn.Count"));
for (ItemStack items : shooter.getInventory().getContents()) {
if (items != null && items.getType() == XMaterial.ARROW.parseMaterial() && items.getAmount() < 64) {
if (shooter.hasPermission("kp.arrowreturn")) {
shooter.getInventory().addItem(arrowToAdd);
return;
}
}
}
if (shooter.getInventory().firstEmpty() == -1) {
shooter.sendMessage(config.fetchString("Combat.ArrowReturn.NoSpace"));
} else {
shooter.getInventory().addItem(arrowToAdd);
}
}
}
}
@@ -1,5 +1,6 @@
package com.planetgallium.kitpvp.listener;
import com.planetgallium.kitpvp.game.Kits;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -14,9 +15,11 @@ import com.planetgallium.kitpvp.util.Toolkit;
public class AttackListener implements Listener {
private Resources resources;
private Kits kits;
public AttackListener(Game plugin) {
this.resources = plugin.getResources();
this.kits = plugin.getArena().getKits();
}
@EventHandler
@@ -31,16 +34,16 @@ public class AttackListener implements Listener {
if (resources.getConfig().getBoolean("Arena.NoKitProtection")) {
if (!Game.getInstance().getArena().getKits().hasKit(damagedPlayer.getName())) {
if (!kits.hasKit(damagedPlayer.getName())) {
damager.sendMessage(resources.getMessages().getString("Messages.Error.Invincible"));
damager.sendMessage(resources.getMessages().fetchString("Messages.Error.Invincible"));
e.setCancelled(true);
}
if (Game.getInstance().getArena().getKits().hasKit(damagedPlayer.getName()) && !Game.getInstance().getArena().getKits().hasKit(damager.getName())) {
if (kits.hasKit(damagedPlayer.getName()) && !kits.hasKit(damager.getName())) {
damager.sendMessage(resources.getMessages().getString("Messages.Error.Kit"));
damager.sendMessage(resources.getMessages().fetchString("Messages.Error.Kit"));
e.setCancelled(true);
}
@@ -55,31 +58,28 @@ public class AttackListener implements Listener {
@EventHandler
public void onDamage(EntityDamageEvent e) {
if (e.getEntity() instanceof Player) {
Player damagedPlayer = (Player) e.getEntity();
// System.out.println("Damaged player: " + damagedPlayer.getName());
// bot is not doing damage to the player
if (Toolkit.inArena(damagedPlayer)) {
// System.out.println("Damaged player is in arena");
if (resources.getConfig().getBoolean("Arena.NoKitProtection")) {
if (!Game.getInstance().getArena().getKits().hasKit(damagedPlayer.getName())) {
// System.out.println("NoKitProt enabled");
if (!kits.hasKit(damagedPlayer.getName())) {
// System.out.println("has kit");
if (e.getCause() != DamageCause.VOID) {
// System.out.println("Cancelled damage");
e.setCancelled(true);
}
}
}
}
}
}
}
@@ -12,8 +12,8 @@ import com.planetgallium.kitpvp.util.Toolkit;
public class ChatListener implements Listener {
private Arena arena;
private Resources resources;
private final Arena arena;
private final Resources resources;
public ChatListener(Game plugin) {
this.arena = plugin.getArena();
@@ -26,12 +26,9 @@ public class ChatListener implements Listener {
if (resources.getConfig().getBoolean("Chat.Enabled") && Toolkit.inArena(e.getPlayer())) {
Player p = e.getPlayer();
String levelPrefix = arena.getUtilities().getPlayerLevelPrefix(p.getName());
String playerLevel = String.valueOf(arena.getStats().getStat("level", p.getName()));
String levelPrefix = resources.getLevels().getString("Levels.Levels." + playerLevel + ".Prefix")
.replace("%level%", playerLevel);
String format = resources.getConfig().getString("Chat.Format")
String format = resources.getConfig().fetchString("Chat.Format")
.replace("%player%", "%s")
.replace("%message%", "%s")
.replace("%level%", levelPrefix);
@@ -11,7 +11,6 @@ import org.bukkit.World;
import org.bukkit.entity.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
@@ -28,21 +27,22 @@ import java.util.List;
public class DeathListener implements Listener {
private final Game plugin;
private final Arena arena;
private final Resources resources;
private final Resource config;
public DeathListener(Game plugin) {
this.plugin = plugin;
this.arena = plugin.getArena();
this.resources = plugin.getResources();
this.config = resources.getConfig();
}
@EventHandler
public void onDeath(PlayerDeathEvent e) {
// investigate possible memory leak when FancyDeath is enabled
if (Toolkit.inArena(e.getEntity())) {
Player victim = e.getEntity();
@@ -52,11 +52,12 @@ public class DeathListener implements Listener {
e.getDrops().clear();
}
setDeathMessage(victim);
respawnPlayer(victim);
setDeathMessage(victim);
arena.getStats().addToStat("deaths", victim.getName(), 1);
arena.getStats().removeExperience(victim.getName(), resources.getLevels().getInt("Levels.Options.Experience-Taken-On-Death"));
arena.getStats().removeExperience(victim.getName(),
resources.getLevels().getInt("Levels.Options.Experience-Taken-On-Death"));
if (config.getBoolean("Arena.DeathParticle")) {
victim.getWorld().playEffect(victim.getLocation().add(0.0D, 1.0D, 0.0D), Effect.STEP_SOUND, 152);
@@ -64,76 +65,62 @@ public class DeathListener implements Listener {
Toolkit.runCommands(victim, config.getStringList("Death.Commands"), "%victim%", victim.getName());
broadcast(victim.getWorld(), XSound.matchXSound(config.getString("Death.Sound.Sound")).get().parseSound(), 1, config.getInt("Death.Sound.Pitch"));
broadcast(victim.getWorld(),
XSound.matchXSound(config.fetchString("Death.Sound.Sound")).get().parseSound(),
1,
config.getInt("Death.Sound.Pitch"));
}
}
@EventHandler
public void onRespawn(PlayerRespawnEvent e) {
if (Toolkit.inArena(e.getPlayer())) {
if (!config.getBoolean("Arena.FancyDeath")) {
Player p = e.getPlayer();
new BukkitRunnable() {
@Override
public void run() {
arena.toSpawn(p, p.getWorld().getName());
}
}.runTaskLater(Game.getInstance(), 1L);
}.runTaskLater(plugin, 1L);
}
}
}
private void respawnPlayer(Player victim) {
if (!victim.isOnline()) {
return;
}
if (config.getBoolean("Arena.FancyDeath")) {
Location deathLocation = victim.getLocation();
new BukkitRunnable() {
@Override
public void run() {
victim.spigot().respawn();
victim.teleport(deathLocation);
victim.setGameMode(GameMode.SPECTATOR);
}
}.runTaskLater(Game.getInstance(), 1L);
}.runTaskLater(plugin, 1L);
arena.removePlayer(victim);
new BukkitRunnable() {
int time = config.getInt("Death.Title.Time");
@Override
public void run() {
if (time != 0) {
Titles.sendTitle(victim, 0, 21, 0, config.getString("Death.Title.Title"), config.getString("Death.Title.Subtitle").replace("%seconds%", String.valueOf(time)));
Titles.sendTitle(victim, 0, 21, 0,
config.fetchString("Death.Title.Title"),
config.fetchString("Death.Title.Subtitle")
.replace("%seconds%", String.valueOf(time)));
XSound.play(victim, "UI_BUTTON_CLICK, 1, 1");
time--;
} else {
if (config.getBoolean("Arena.ClearInventoryOnRespawn")) {
victim.getInventory().clear();
victim.getInventory().setArmorContents(null);
@@ -141,47 +128,43 @@ public class DeathListener implements Listener {
arena.addPlayer(victim, true, config.getBoolean("Arena.GiveItemsOnRespawn"));
victim.sendMessage(config.getString("Death.Title.Message"));
victim.sendMessage(config.fetchString("Death.Title.Message"));
victim.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 30, 0));
XSound.play(victim, "ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1");
Toolkit.runCommands(victim, config.getStringList("Respawn.Commands"), "none", "none");
cancel();
}
}
}.runTaskTimer(Game.getInstance(), 0L, 20L);
} else {
}.runTaskTimer(plugin, 0L, 20L);
} else {
arena.removePlayer(victim);
if (config.getBoolean("Arena.ClearInventoryOnRespawn")) {
victim.getInventory().clear();
victim.getInventory().setArmorContents(null);
}
new BukkitRunnable() {
@Override
public void run() {
arena.addPlayer(victim, true, config.getBoolean("Arena.GiveItemsOnRespawn"));
Toolkit.runCommands(victim, config.getStringList("Respawn.Commands"), "none", "none");
Toolkit.runCommands(victim, config.getStringList("Respawn.Commands"),
"none", "none");
}
}.runTaskLater(Game.getInstance(), 1L);
}.runTaskLater(plugin, 1L);
}
}
private void setDeathMessage(Player victim) {
if (victim.getLastDamageCause() == null) {
broadcast(victim.getWorld(), getDeathMessage(victim, null, "Unknown"));
return;
}
DamageCause cause = victim.getLastDamageCause().getCause();
if (cause == DamageCause.PROJECTILE && getShooter(victim.getLastDamageCause()).getType() == EntityType.PLAYER) {
@@ -193,7 +176,7 @@ public class DeathListener implements Listener {
// } else if (cause == DamageCause.ENTITY_ATTACK) {
//
// broadcast(victim.getWorld(), config.getString("Death.Messages.Player").replace("%victim%", victim.getName()).replace("%killer%", victim.getKiller().getName()));
// broadcast(victim.getWorld(), config.fetchString("Death.Messages.Player").replace("%victim%", victim.getName()).replace("%killer%", victim.getKiller().getName()));
// creditWithKill(victim, victim.getKiller());
} else if (victim.getKiller() != null) {
@@ -265,11 +248,8 @@ public class DeathListener implements Listener {
}
private void creditWithKill(Player victim, Player killer) {
if (victim != null && killer != null) {
if (!victim.getName().equals(killer.getName())) {
arena.getStats().addToStat("kills", killer.getName(), 1);
arena.getStats().addExperience(killer, resources.getLevels().getInt("Levels.Options.Experience-Given-On-Kill"));
@@ -278,37 +258,24 @@ public class DeathListener implements Listener {
Toolkit.runCommands(killer, killCommands, "%killer%", killer.getName());
if (resources.getScoreboard().getBoolean("Scoreboard.General.Enabled")) {
new BukkitRunnable() {
@Override
public void run() {
if (killer instanceof Player) {
arena.updateScoreboards(killer, false);
}
arena.updateScoreboards(killer, false);
}
}.runTaskLater(Game.getInstance(), 20L);
}.runTaskLater(plugin, 20L);
}
}
}
}
private String getDeathMessage(Player victim, Player killer, String type) {
String deathMessage = config.getString("Death.Messages." + type);
String deathMessage = config.fetchString("Death.Messages." + type);
if (victim != null && killer != null) {
if (victim.getName().equals(killer.getName())) {
deathMessage = config.getString("Death.Messages.Suicide");
deathMessage = config.fetchString("Death.Messages.Suicide");
}
}
@@ -316,7 +283,7 @@ public class DeathListener implements Listener {
deathMessage = deathMessage.replace("%killer%", killer.getName())
.replace("%killer_health%", String.valueOf(Toolkit.round(killer.getHealth(), 2)));
} else {
deathMessage = config.getString("Death.Messages.Unknown"); // if killer is null (left the server, or some other unknown reason)
deathMessage = config.fetchString("Death.Messages.Unknown"); // if killer is null (left the server, or some other unknown reason)
}
if (victim != null) {
@@ -4,7 +4,6 @@ import com.cryptomorin.xseries.XSound;
import com.planetgallium.kitpvp.Game;
import com.planetgallium.kitpvp.game.Arena;
import com.planetgallium.kitpvp.util.Resource;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -21,7 +20,7 @@ public class HitListener implements Listener {
this.arena = plugin.getArena();
this.config = plugin.getResources().getConfig();
String soundString = config.getString("Combat.HitSound.Sound") + ", 1, " + config.getInt("Combat.HitSound.Pitch");
String soundString = config.fetchString("Combat.HitSound.Sound") + ", 1, " + config.getInt("Combat.HitSound.Pitch");
this.hitSound = XSound.parse(soundString);
}
@@ -7,6 +7,7 @@ import java.util.Random;
import com.cryptomorin.xseries.XMaterial;
import com.cryptomorin.xseries.XSound;
import com.planetgallium.kitpvp.api.Kit;
import com.planetgallium.kitpvp.game.Utilities;
import com.planetgallium.kitpvp.util.Resource;
import org.bukkit.*;
import org.bukkit.configuration.ConfigurationSection;
@@ -35,14 +36,18 @@ import com.planetgallium.kitpvp.util.Resources;
import com.planetgallium.kitpvp.util.Toolkit;
public class ItemListener implements Listener {
private final Game plugin;
private final Arena arena;
private final Utilities utilities;
private final Resources resources;
private final Resource config;
private final Resource abilities;
public ItemListener(Game plugin) {
this.plugin = plugin;
this.arena = plugin.getArena();
this.utilities = plugin.getArena().getUtilities();
this.resources = plugin.getResources();
this.config = resources.getConfig();
this.abilities = resources.getAbilities();
@@ -91,9 +96,9 @@ public class ItemListener implements Listener {
} else if (item.getType() == XMaterial.TNT.parseMaterial()) {
if (config.getBoolean("TNT.Enabled") && Toolkit.hasMatchingDisplayName(item, config.getString("TNT.Name"))) {
if (config.getBoolean("TNT.Enabled") && Toolkit.hasMatchingDisplayName(item, config.fetchString("TNT.Name"))) {
if (!arena.isCombatActionPermittedInRegion(p)) {
if (!utilities.isCombatActionPermittedInRegion(p)) {
return;
}
@@ -134,11 +139,11 @@ public class ItemListener implements Listener {
useAbilityItem(p, p, item, "Warper");
} else {
p.sendMessage(resources.getMessages().getString("Messages.Other.Players"));
p.sendMessage(resources.getMessages().fetchString("Messages.Other.Players"));
}
} else {
p.sendMessage(resources.getMessages().getString("Messages.Other.Players"));
p.sendMessage(resources.getMessages().fetchString("Messages.Other.Players"));
}
}
@@ -188,7 +193,7 @@ public class ItemListener implements Listener {
}
}.runTaskLater(Game.getInstance(), 100L);
}.runTaskLater(plugin, 100L);
}
@@ -210,7 +215,7 @@ public class ItemListener implements Listener {
Entity entity = p.getWorld().spawn(p.getLocation(), TNTPrimed.class);
entity.setCustomName(p.getName());
String bomberSound = abilities.getString("Abilities.Bomber.Sound.Sound");
String bomberSound = abilities.fetchString("Abilities.Bomber.Sound.Sound");
p.playSound(p.getLocation(), XSound.matchXSound(bomberSound).get().parseSound(),
1, abilities.getInt("Abilities.Bomber.Sound.Pitch"));
@@ -224,7 +229,7 @@ public class ItemListener implements Listener {
}
}.runTaskTimer(Game.getInstance(), 0L, 20L);
}.runTaskTimer(plugin, 0L, 20L);
useAbilityItem(p, null, item, "Bomber");
@@ -232,16 +237,16 @@ public class ItemListener implements Listener {
} else if (item.getType() == XMaterial.SLIME_BALL.parseMaterial() && item.hasItemMeta()) {
if (Toolkit.hasMatchingDisplayName(item, abilities.getString("Abilities.Archer.Item.NoFire"))) {
if (Toolkit.hasMatchingDisplayName(item, abilities.fetchString("Abilities.Archer.Item.NoFire"))) {
item.setType(XMaterial.MAGMA_CREAM.parseMaterial());
meta.setDisplayName(Toolkit.translate(abilities.getString("Abilities.Archer.Item.Fire")));
meta.setDisplayName(Toolkit.translate(abilities.fetchString("Abilities.Archer.Item.Fire")));
item.setItemMeta(meta);
Toolkit.setMainHandItem(p, item);
if (abilities.getBoolean("Abilities.Archer.Message.Enabled")) {
p.sendMessage(abilities.getString("Abilities.Archer.Message.Fire"));
p.sendMessage(abilities.fetchString("Abilities.Archer.Message.Fire"));
}
XSound.play(p, "UI_BUTTON_CLICK, 1, 1");
@@ -250,16 +255,16 @@ public class ItemListener implements Listener {
} else if (item.getType() == XMaterial.MAGMA_CREAM.parseMaterial() && item.hasItemMeta()) {
if (Toolkit.hasMatchingDisplayName(item, abilities.getString("Abilities.Archer.Item.Fire"))) {
if (Toolkit.hasMatchingDisplayName(item, abilities.fetchString("Abilities.Archer.Item.Fire"))) {
item.setType(XMaterial.SLIME_BALL.parseMaterial());
meta.setDisplayName(Toolkit.translate(abilities.getString("Abilities.Archer.Item.NoFire")));
meta.setDisplayName(Toolkit.translate(abilities.fetchString("Abilities.Archer.Item.NoFire")));
item.setItemMeta(meta);
Toolkit.setMainHandItem(p, item);
if (abilities.getBoolean("Abilities.Archer.Message.Enabled")) {
p.sendMessage(Toolkit.translate(abilities.getString("Abilities.Archer.Message.NoFire")));
p.sendMessage(Toolkit.translate(abilities.fetchString("Abilities.Archer.Message.NoFire")));
}
XSound.play(p, "UI_BUTTON_CLICK, 1, 1");
@@ -271,9 +276,9 @@ public class ItemListener implements Listener {
/* Kit Item and custom Arena Items */
if (config.contains("Items.Kits") &&
item.getType() == XMaterial.matchXMaterial(config.getString("Items.Kits.Material")).get().parseMaterial()) {
item.getType() == XMaterial.matchXMaterial(config.fetchString("Items.Kits.Material")).get().parseMaterial()) {
if (Toolkit.hasMatchingDisplayName(item, config.getString("Items.Kits.Name"))) {
if (Toolkit.hasMatchingDisplayName(item, config.fetchString("Items.Kits.Name"))) {
Toolkit.runCommands(p, config.getStringList("Items.Kits.Commands"), "none", "none");
@@ -295,9 +300,9 @@ public class ItemListener implements Listener {
if (config.getBoolean(itemPath + ".Enabled")) {
if (item.getType() == XMaterial.matchXMaterial(config.getString(itemPath + ".Material")).get().parseMaterial()) {
if (item.getType() == XMaterial.matchXMaterial(config.fetchString(itemPath + ".Material")).get().parseMaterial()) {
if (Toolkit.hasMatchingDisplayName(item, config.getString(itemPath + ".Name"))) {
if (Toolkit.hasMatchingDisplayName(item, config.fetchString(itemPath + ".Name"))) {
Toolkit.runCommands(p, config.getStringList(itemPath + ".Commands"), "none", "none");
e.setCancelled(true);
@@ -371,31 +376,24 @@ public class ItemListener implements Listener {
}
private boolean isAbilityItem(Player p, String kitName, ItemStack interactedItem) {
if (Toolkit.hasMatchingDisplayName(interactedItem, abilities.fetchString("Abilities." + kitName + ".Item.Name"))) {
String abilityPermission = "kp.ability." + kitName.toLowerCase();
if (arena.getKits().hasKit(p.getName())) {
if (Toolkit.hasMatchingDisplayName(interactedItem, abilities.getString("Abilities." + kitName + ".Item.Name"))) {
String abilityPermission = "kp.ability." + kitName.toLowerCase();
if (p.hasPermission(abilityPermission)) {
if (arena.isCombatActionPermittedInRegion(p)) {
return true;
}
} else {
p.sendMessage(resources.getMessages().getString("Messages.General.Permission").replace("%permission%", abilityPermission));
if (p.hasPermission(abilityPermission)) {
if (config.getBoolean("Arena.AbilitiesRequireKit") && !arena.getKits().hasKit(p.getName())) {
p.sendMessage(resources.getMessages().fetchString("Messages.Error.Kit"));
return false;
}
if (utilities.isCombatActionPermittedInRegion(p)) {
return true;
}
} else {
p.sendMessage(resources.getMessages().fetchString("Messages.General.Permission").replace("%permission%", abilityPermission));
}
}
return false;
}
private void useAbilityItem(Player p, Player clicked, ItemStack abilityItem, String kitName) {
@@ -403,7 +401,7 @@ public class ItemListener implements Listener {
String abilityPrefix = "Abilities." + kitName;
if (abilities.getBoolean(abilityPrefix + ".Message.Enabled")) {
String abilityMessage = abilities.getString(abilityPrefix + ".Message.Message");
String abilityMessage = abilities.fetchString(abilityPrefix + ".Message.Message");
if (clicked != null) abilityMessage = abilityMessage.replace("%player%", clicked.getName());
p.sendMessage(abilityMessage);
}
@@ -412,7 +410,7 @@ public class ItemListener implements Listener {
Toolkit.setMainHandItem(p, abilityItem);
if (abilities.getBoolean(abilityPrefix + ".Sound.Enabled")) {
XSound.play(p, abilities.getString(abilityPrefix + ".Sound.Sound") + ", 1, " + abilities.getInt(abilityPrefix + ".Sound.Pitch"));
XSound.play(p, abilities.fetchString(abilityPrefix + ".Sound.Sound") + ", 1, " + abilities.getInt(abilityPrefix + ".Sound.Pitch"));
}
}
@@ -428,14 +426,14 @@ public class ItemListener implements Listener {
if (p.hasPermission("kp.ability.archer")) {
int ammoSlot = getItemByMeta(Material.MAGMA_CREAM, abilities.getString("Abilities.Archer.Item.Fire"), p);
int ammoSlot = getItemByMeta(Material.MAGMA_CREAM, abilities.fetchString("Abilities.Archer.Item.Fire"), p);
if (ammoSlot != -1) {
ItemStack ammo = p.getInventory().getItem(ammoSlot);
e.getProjectile().setFireTicks(1000);
p.playSound(p.getLocation(), XSound.matchXSound(abilities.getString("Abilities.Archer.Sound.Sound")).get().parseSound(), 1, (int) abilities.getInt("Abilities.Archer.Sound.Pitch"));
p.playSound(p.getLocation(), XSound.matchXSound(abilities.fetchString("Abilities.Archer.Sound.Sound")).get().parseSound(), 1, (int) abilities.getInt("Abilities.Archer.Sound.Pitch"));
if (ammo.getAmount() == 1) {
p.getInventory().setItem(ammoSlot, new ItemStack(Material.AIR));
@@ -503,14 +501,14 @@ public class ItemListener implements Listener {
shooter.getInventory().setItem(slot, potionStack);
if (abilities.getBoolean("Abilities.Witch.Message.Enabled")) {
shooter.sendMessage(Toolkit.translate(abilities.getString("Abilities.Witch.Message.Message")));
shooter.sendMessage(Toolkit.translate(abilities.fetchString("Abilities.Witch.Message.Message")));
}
XSound.play(shooter, abilities.getString("Abilities.Witch.Sound.Sound") + ", 1, " + abilities.getInt("Abliities.Witch.Sound.Pitch"));
XSound.play(shooter, abilities.fetchString("Abilities.Witch.Sound.Sound") + ", 1, " + abilities.getInt("Abliities.Witch.Sound.Pitch"));
}
}.runTaskLater(Game.getInstance(), 5 * 20);
}.runTaskLater(plugin, 5 * 20);
}
@@ -584,8 +582,8 @@ public class ItemListener implements Listener {
Player shooter = (Player) egg.getShooter();
Location shooterLocation = shooter.getLocation();
if (!arena.isCombatActionPermittedInRegion(damagedPlayer)) {
shooter.sendMessage(resources.getMessages().getString("Messages.Error.PVP"));
if (!utilities.isCombatActionPermittedInRegion(damagedPlayer)) {
shooter.sendMessage(resources.getMessages().fetchString("Messages.Error.PVP"));
return;
}
@@ -593,12 +591,12 @@ public class ItemListener implements Listener {
damagedPlayer.teleport(shooterLocation);
if (abilities.getBoolean("Abilities.Trickster.Message.Enabled")) {
shooter.sendMessage(Toolkit.translate(abilities.getString("Abilities.Trickster.Message.Message").replace("%player%", damagedPlayer.getName())));
shooter.sendMessage(Toolkit.translate(abilities.fetchString("Abilities.Trickster.Message.Message").replace("%player%", damagedPlayer.getName())));
}
if (abilities.getBoolean("Abilities.Trickster.Sound.Enabled")) {
XSound.play(shooter, abilities.getString("Abilities.Trickster.Sound.Sound") + ", 1, " + abilities.getInt("Abilities.Trickster.Sound.Pitch"));
XSound.play(damagedPlayer, abilities.getString("Abilities.Trickster.Sound.Sound") + ", 1, " + abilities.getInt("Abilities.Trickster.Sound.Pitch"));
XSound.play(shooter, abilities.fetchString("Abilities.Trickster.Sound.Sound") + ", 1, " + abilities.getInt("Abilities.Trickster.Sound.Pitch"));
XSound.play(damagedPlayer, abilities.fetchString("Abilities.Trickster.Sound.Sound") + ", 1, " + abilities.getInt("Abilities.Trickster.Sound.Pitch"));
}
}
@@ -1,7 +1,6 @@
package com.planetgallium.kitpvp.listener;
import com.planetgallium.kitpvp.util.Resource;
import com.planetgallium.kitpvp.util.Resources;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -16,80 +15,57 @@ public class JoinListener implements Listener {
private final Game plugin;
private final Arena arena;
private final Resources resources;
private final Resource config;
public JoinListener(Game plugin) {
this.plugin = plugin;
this.arena = plugin.getArena();
this.resources = plugin.getResources();
this.config = resources.getConfig();
this.config = plugin.getResources().getConfig();
}
@EventHandler
public void onJoin(PlayerJoinEvent e) {
Player p = e.getPlayer();
// Update checker
if (plugin.needsUpdate()) {
if (p.isOp()) {
p.sendMessage(Toolkit.translate("&7[&b&lKIT-PVP&7] &aAn update was found: v" + plugin.getUpdateVersion() + " https://www.spigotmc.org/resources/27107/"));
p.sendMessage(Toolkit.translate("&7[&b&lKIT-PVP&7] &aAn update was found: v" +
plugin.getUpdateVersion() + " https://www.spigotmc.org/resources/27107/"));
}
}
arena.getStats().createPlayer(p);
if (p.getName().equals("cervinakuy")) {
e.setJoinMessage(Toolkit.translate("&7[&b&lKIT-PVP&7] &7The Developer of &bKitPvP" +
" &7has joined the server."));
}
if (Toolkit.inArena(p)) {
if (config.getBoolean("Arena.ClearInventoryOnJoin")) {
p.getInventory().clear();
p.getInventory().setArmorContents(null);
}
arena.addPlayer(p, config.getBoolean("Arena.ToSpawnOnJoin"), config.getBoolean("Arena.GiveItemsOnJoin"));
}
if (p.getName().equals("cervinakuy")) {
e.setJoinMessage(Toolkit.translate("&7[&b&lKIT-PVP&7] &7The Developer of &bKitPvP &7has joined the server."));
arena.addPlayer(p, config.getBoolean("Arena.ToSpawnOnJoin"),
config.getBoolean("Arena.GiveItemsOnJoin"));
}
}
@EventHandler
public void onWorldChange(PlayerChangedWorldEvent e) {
Player p = e.getPlayer();
if (Toolkit.inArena(p)) {
if (config.getBoolean("Arena.ClearInventoryOnJoin")) {
p.getInventory().clear();
p.getInventory().setArmorContents(null);
}
arena.addPlayer(p, config.getBoolean("Arena.ToSpawnOnJoin"), config.getBoolean("Arena.GiveItemsOnJoin"));
} else if (Toolkit.inArena(e.getFrom())) {
// if they left from the kitpvp arena
if (config.getBoolean("Arena.ClearInventoryOnLeave")) {
p.getInventory().clear();
p.getInventory().setArmorContents(null);
}
arena.removePlayer(p);
arena.addPlayer(p, config.getBoolean("Arena.ToSpawnOnJoin"),
config.getBoolean("Arena.GiveItemsOnJoin"));
}
}
}
@@ -4,6 +4,7 @@ import com.planetgallium.kitpvp.util.Toolkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import com.planetgallium.kitpvp.Game;
@@ -11,21 +12,35 @@ import com.planetgallium.kitpvp.game.Arena;
public class LeaveListener implements Listener {
private Arena arena;
private final Game plugin;
private final Arena arena;
public LeaveListener(Game plugin) {
this.plugin = plugin;
this.arena = plugin.getArena();
}
@EventHandler
public void onLeave(PlayerQuitEvent e) {
Player p = e.getPlayer();
if (Toolkit.inArena(p)) {
arena.deletePlayer(p);
}
}
@EventHandler
public void onWorldChange(PlayerChangedWorldEvent e) {
if (Toolkit.inArena(e.getFrom())) { // if they left from a kitpvp arena
Player p = e.getPlayer();
if (plugin.getConfig().getBoolean("Arena.ClearInventoryOnLeave")) {
p.getInventory().clear();
p.getInventory().setArmorContents(null);
}
arena.removePlayer(p);
// no need to clear stats from cache; that will be done on player quit above
}
}
}
@@ -19,11 +19,13 @@ import org.bukkit.scheduler.BukkitRunnable;
public class MenuListener implements Listener {
private final Game plugin;
private final Arena arena;
private final Resource config;
private final Resource menuConfig;
public MenuListener(Game plugin) {
this.plugin = plugin;
this.arena = plugin.getArena();
this.config = plugin.getResources().getConfig();
this.menuConfig = plugin.getResources().getMenu();
@@ -32,12 +34,8 @@ public class MenuListener implements Listener {
@EventHandler
public void onClick(InventoryClickEvent e) {
// System.out.println("sldfjsdkfjk j");
if (e.getClickedInventory() != null) {
// System.out.println("here");
Player p = (Player) e.getWhoClicked();
Inventory originInventory = e.getClickedInventory();
@@ -75,7 +73,7 @@ public class MenuListener implements Listener {
Toolkit.runCommands(p, menuConfig.getStringList(itemPath + ".Commands." + clickType), "none", "none");
}
}.runTaskLater(Game.getInstance(), 1L);
}.runTaskLater(plugin, 1L);
}
@@ -96,7 +94,7 @@ public class MenuListener implements Listener {
Toolkit.runCommands(p, config.getStringList("PreviewMenuBackArrowCommands"), "none", "none");
}
}.runTaskLater(Game.getInstance(), 1L);
}.runTaskLater(plugin, 1L);
} else {
@@ -110,11 +108,4 @@ public class MenuListener implements Listener {
}
@EventHandler
public void onThing(PlayerDropItemEvent e) {
//System.out.println("Tesdfjksdfk");
}
}
@@ -44,12 +44,12 @@ public class SignListener implements Listener {
if (regularSignTypes.contains(signType)) {
renameSign(e, "Signs." + Toolkit.capitalizeFirstChar(signType), null, null);
p.sendMessage(messages.getString("Messages.Other.Sign"));
p.sendMessage(messages.fetchString("Messages.Other.Sign"));
} else if (customSignTypes.contains(signType)) {
String placeholderKey = "%" + signType + "%";
String placeholderValue = e.getLine(2);
renameSign(e, "Signs." + Toolkit.capitalizeFirstChar(signType), placeholderKey, placeholderValue);
p.sendMessage(messages.getString("Messages.Other.Sign"));
p.sendMessage(messages.fetchString("Messages.Other.Sign"));
}
}
@@ -79,7 +79,7 @@ public class SignListener implements Listener {
for (int i = 0; i < 3; i++) {
String signLine = sign.getLine(i);
String configSignLine = signs.getString("Signs." + signType + ".Line-" + (i + 1));
String configSignLine = signs.fetchString("Signs." + signType + ".Line-" + (i + 1));
if (!signLine.equals(configSignLine)) {
mismatchedLines.add(new String[]{configSignLine, signLine});
@@ -106,7 +106,7 @@ public class SignListener implements Listener {
for (int i = 0; i < 3; i++) {
String line = signs.getString(path + ".Line-" + (i + 1));
String line = signs.fetchString(path + ".Line-" + (i + 1));
if (placeholder != null && placeholderValue != null)
line = line.replace(placeholder, placeholderValue);
@@ -16,11 +16,13 @@ import org.bukkit.scheduler.BukkitRunnable;
import com.planetgallium.kitpvp.Game;
public class SoupListener implements Listener {
private Resource config;
private int soupBoost;
private final Game plugin;
private final Resource config;
private final int soupBoost;
public SoupListener(Game plugin) {
this.plugin = plugin;
this.config = plugin.getResources().getConfig();
this.soupBoost = plugin.getConfig().getInt("Soups.RegenAmount");
}
@@ -55,7 +57,7 @@ public class SoupListener implements Listener {
}
if (count < config.getInt("Kill.SoupReward.Amount")) {
killer.sendMessage(config.getString("Kill.SoupReward.NoSpace").replace("%amount%", String.valueOf((config.getInt("Kill.SoupReward.Amount") - count))));
killer.sendMessage(config.fetchString("Kill.SoupReward.NoSpace").replace("%amount%", String.valueOf((config.getInt("Kill.SoupReward.Amount") - count))));
} else {
count = config.getInt("Kill.SoupReward.Amount");
}
@@ -63,7 +65,7 @@ public class SoupListener implements Listener {
ItemStack soup = XMaterial.MUSHROOM_STEW.parseItem();
ItemMeta soupMeta = soup.getItemMeta();
soupMeta.setDisplayName(config.getString("Soups.Name"));
soupMeta.setDisplayName(config.fetchString("Soups.Name"));
soupMeta.setLore(Toolkit.colorizeList(config.getStringList("Soups.Lore")));
soup.setItemMeta(soupMeta);
@@ -76,7 +78,7 @@ public class SoupListener implements Listener {
}
}.runTaskLater(Game.getInstance(), config.getInt("Kill.SoupReward.Delay") * 20);
}.runTaskLater(plugin, config.getInt("Kill.SoupReward.Delay") * 20);
}
@@ -106,7 +108,7 @@ public class SoupListener implements Listener {
if (p.getHealth() < 20.0) {
p.setHealth(p.getHealth() + (double) soupBoost >= 20.0 ? 20.0 : p.getHealth() + (double) soupBoost);
p.playSound(p.getLocation(), XSound.matchXSound(config.getString("Soups.Sound")).get().parseSound(), 1, (float) config.getInt("Soups.Pitch"));
p.playSound(p.getLocation(), XSound.matchXSound(config.fetchString("Soups.Sound")).get().parseSound(), 1, (float) config.getInt("Soups.Pitch"));
if (Toolkit.getMainHandItem(p).getType() == XMaterial.MUSHROOM_STEW.parseMaterial()) {
@@ -85,14 +85,14 @@ public class TrackerListener implements Listener {
double nearestPlayerDistance = Toolkit.round(Double.parseDouble(nearestPlayerData[1]), 1);
if (nearestPlayer != null && nearestPlayer.isOnline()) {
compassMeta.setDisplayName(resources.getConfig().getString("PlayerTracker.Message")
compassMeta.setDisplayName(resources.getConfig().fetchString("PlayerTracker.Message")
.replace("%nearestplayer%", nearestPlayer.getName())
.replace("%distance%", String.valueOf(nearestPlayerDistance)));
player.setCompassTarget(nearestPlayer.getLocation());
}
} else {
compassMeta.setDisplayName(resources.getConfig().getString("PlayerTracker.NoneOnline"));
compassMeta.setDisplayName(resources.getConfig().fetchString("PlayerTracker.NoneOnline"));
}
compass.setItemMeta(compassMeta);
@@ -11,16 +11,16 @@ import java.util.List;
public class KitMenu {
private Menu menu;
private Resources resources;
private final Resources resources;
public KitMenu(Resources resources) {
this.resources = resources;
create();
rebuildCache();
}
private void create() {
this.menu = new Menu(resources.getMenu().getString("Menu.General.Title"), new KitHolder(), resources.getMenu().getInt("Menu.General.Size"));
this.menu = new Menu(resources.getMenu().fetchString("Menu.General.Title"), new KitHolder(), resources.getMenu().getInt("Menu.General.Size"));
ConfigurationSection section = resources.getMenu().getConfigurationSection("Menu.Items");
@@ -28,8 +28,8 @@ public class KitMenu {
String itemPath = "Menu.Items." + slot;
String name = resources.getMenu().getString(itemPath + ".Name");
Material material = XMaterial.matchXMaterial(resources.getMenu().getString(itemPath + ".Material")).get().parseMaterial();
String name = resources.getMenu().fetchString(itemPath + ".Name");
Material material = XMaterial.matchXMaterial(resources.getMenu().fetchString(itemPath + ".Material")).get().parseMaterial();
List<String> lore = resources.getMenu().getStringList(itemPath + ".Lore");
menu.addItem(name, material, lore, Integer.valueOf(slot));
@@ -38,7 +38,7 @@ public class KitMenu {
}
public void clearCache() {
public void rebuildCache() {
create();
}
@@ -6,6 +6,7 @@ import java.util.List;
import com.cryptomorin.xseries.XMaterial;
import com.planetgallium.kitpvp.api.Kit;
import com.planetgallium.kitpvp.util.CacheManager;
import com.planetgallium.kitpvp.util.Resources;
import org.bukkit.entity.Player;
import com.planetgallium.kitpvp.util.Menu;
@@ -13,9 +14,10 @@ import org.bukkit.potion.PotionEffect;
public class PreviewMenu {
private Menu create(Kit kit) {
Menu previewMenu = new Menu("Previewing: " + kit.getName(), new PreviewHolder(), 54);
private Menu create(Kit kit, Resources resources) {
String previewMenuTitle = resources.getMessages().fetchString("Messages.Other.PreviewMenuTitle")
.replace("%kit%", kit.getName());
Menu previewMenu = new Menu(previewMenuTitle, new PreviewHolder(), 54);
// ARMOR //
@@ -47,7 +49,9 @@ public class PreviewMenu {
effectsLore.add("&7None");
}
previewMenu.addItem("&a&lPotion Effects", XMaterial.BREWING_STAND.parseMaterial(), effectsLore, 4);
String menuPotionEffectsItemName =
resources.getMessages().fetchString("Messages.Other.MenuPotionEffectsItemName");
previewMenu.addItem(menuPotionEffectsItemName, XMaterial.BREWING_STAND.parseMaterial(), effectsLore, 4);
// HOTBAR //
@@ -75,21 +79,19 @@ public class PreviewMenu {
}
}
previewMenu.addItem("&cBack to Kits", XMaterial.ARROW.parseMaterial(), new ArrayList<String>(), 8);
String menuBackArrowItemName = resources.getMessages().fetchString("Messages.Other.MenuBackArrowItemName");
previewMenu.addItem(menuBackArrowItemName, XMaterial.ARROW.parseMaterial(), new ArrayList<>(), 8);
CacheManager.getPreviewMenuCache().put(kit.getName(), previewMenu);
return previewMenu;
}
public void open(Player p, Kit kit) {
public void open(Player p, Kit kit, Resources resources) {
Menu previewMenu = CacheManager.getPreviewMenuCache().containsKey(kit.getName()) ?
CacheManager.getPreviewMenuCache().get(kit.getName()) : create(kit);
CacheManager.getPreviewMenuCache().get(kit.getName()) : create(kit, resources);
previewMenu.openMenu(p);
}
}
@@ -19,7 +19,7 @@ public class RefillMenu {
this.menu = new Menu("Refill", null, 54);
for (int i = 0; i < menu.getSize(); i++) {
menu.addItem(resources.getConfig().getString("Soups.Name"), XMaterial.MUSHROOM_STEW.parseMaterial(), resources.getConfig().getStringList("Soups.Lore"), i);
menu.addItem(resources.getConfig().fetchString("Soups.Name"), XMaterial.MUSHROOM_STEW.parseMaterial(), resources.getConfig().getStringList("Soups.Lore"), i);
}
}
@@ -21,13 +21,11 @@ public class CacheManager {
public static Map<String, PlayerData> getStatsCache() { return statsCache; }
public static Map<String, Long> getPlayerAbilityCooldowns(String username) {
if (abilityCooldowns.get(username) == null) {
if (!abilityCooldowns.containsKey(username)) {
abilityCooldowns.put(username, new HashMap<>());
}
return abilityCooldowns.get(username);
}
public static void clearCaches() {
@@ -1,11 +1,13 @@
package com.planetgallium.kitpvp.util;
import com.planetgallium.database.TopEntry;
import com.planetgallium.kitpvp.Game;
import org.apache.commons.lang.StringUtils;
import org.bukkit.entity.Player;
import com.planetgallium.kitpvp.game.Arena;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
@@ -13,12 +15,10 @@ import java.util.Map;
public class Placeholders extends PlaceholderExpansion {
private final Arena arena;
private final Resources resources;
private final Map<String, String> placeholderAPItoBuiltIn;
public Placeholders(Game plugin) {
this.arena = plugin.getArena();
this.resources = plugin.getResources();
this.placeholderAPItoBuiltIn = new HashMap<>();
placeholderAPItoBuiltIn.put("stats_kills", "%kills%");
@@ -30,60 +30,61 @@ public class Placeholders extends PlaceholderExpansion {
placeholderAPItoBuiltIn.put("player_kit", "%kit%");
placeholderAPItoBuiltIn.put("max_level", "%max_level%");
placeholderAPItoBuiltIn.put("max_xp", "%max_xp%");
placeholderAPItoBuiltIn.put("level_prefix", "%level_prefix%");
}
@Override
public String onPlaceholderRequest(Player p, String identifier) {
public String onPlaceholderRequest(Player p, @NotNull String identifier) {
if (p == null) return null;
if (identifier.contains("top")) {
String[] queries = identifier.split("_");
String topType = queries[1]; // ex: kills
String topIdentifier = queries[2]; // ex: amount, player
String possibleTopValue = queries[3]; // 1, 15
int topValue = 1;
if (StringUtils.isNumeric(possibleTopValue)) {
topValue = Integer.parseInt(possibleTopValue);
} else {
Toolkit.printToConsole("%prefix% &cFailed to properly parse placeholder, expected number but received: " + possibleTopValue);
}
PlayerEntry entry = arena.getLeaderboards().getTopN(topType, topValue);
boolean isUsernamePlaceholder = topIdentifier.equals("player");
return isUsernamePlaceholder ? entry.getUsername() : String.valueOf(entry.getData());
return handleLeaderboardPlaceholder(identifier);
}
return translatePlaceholderAPIPlaceholders(identifier, p.getName());
}
private String handleLeaderboardPlaceholder(String identifier) {
String[] queries = identifier.split("_");
String topType = queries[1]; // ex: kills
String topIdentifier = queries[2]; // ex: amount, player
String possibleTopValue = queries[3]; // 1, 15
int topValue = 1; // if number parsing fails, use top player
if (StringUtils.isNumeric(possibleTopValue)) {
topValue = Integer.parseInt(possibleTopValue);
} else {
Toolkit.printToConsole("%prefix% &cFailed to properly parse placeholder, " +
"expected number but received: " + possibleTopValue);
}
TopEntry entry = arena.getLeaderboards().getTopN(topType, topValue);
boolean isUsernamePlaceholder = topIdentifier.equals("player");
return isUsernamePlaceholder ? entry.getIdentifier() : String.valueOf(entry.getValue());
}
public String translatePlaceholderAPIPlaceholders(String placeholderAPIIdentifier, String username) {
if (!placeholderAPItoBuiltIn.containsKey(placeholderAPIIdentifier)) {
Toolkit.printToConsole(String.format("&7[&b&lKIT-PVP&7] &cUnknown placeholder identifier [%s]. Please see plugin page.",
placeholderAPIIdentifier));
if (placeholderAPItoBuiltIn.containsKey(placeholderAPIIdentifier)) {
String toBuiltInPlaceholder = placeholderAPItoBuiltIn.get(placeholderAPIIdentifier);
return arena.getUtilities().replaceBuiltInPlaceholdersIfPresent(toBuiltInPlaceholder, username);
} else {
Toolkit.printToConsole(String.format("&7[&b&lKIT-PVP&7] &cUnknown placeholder identifier [%s]. " +
"Please see plugin page.", placeholderAPIIdentifier));
return "invalid-placeholder";
}
return arena.replaceBuiltInPlaceholdersIfPresent(placeholderAPItoBuiltIn.get(placeholderAPIIdentifier), username);
}
@Override
public boolean canRegister() { return true; }
@Override
public String getAuthor() { return "Cervinakuy"; }
public @NotNull String getAuthor() { return "Cervinakuy"; }
@Override
public String getIdentifier() { return "kitpvp"; }
public @NotNull String getIdentifier() { return "kitpvp"; }
@Override
public String getVersion() { return "1.0.0"; }
public @NotNull String getVersion() { return "1.0.0"; }
}
@@ -1,49 +1,37 @@
package com.planetgallium.kitpvp.util;
import java.util.HashMap;
import java.util.Map;
public class PlayerData {
private int kills, deaths, experience, level;
private final Map<String, Integer> data;
private final Map<String, Long> kitCooldowns;
public PlayerData(int kills, int deaths, int experience, int level) {
this.kills = kills;
this.deaths = deaths;
this.experience = experience;
this.level = level;
this.data = new HashMap<>();
this.kitCooldowns = new HashMap<>();
data.put("kills", kills);
data.put("deaths", deaths);
data.put("experience", experience);
data.put("level", level);
}
public int getDataByIdentifier(String identifier) {
switch (identifier) {
case "kills": return getKills();
case "deaths": return getDeaths();
case "experience": return getExperience();
case "level": return getLevel();
}
return -1;
public void setData(String identifier, int value) {
data.put(identifier, value);
}
public void setDataByIdentifier(String identifier, int data) {
switch (identifier) {
case "kills": setKills(data); break;
case "deaths": setDeaths(data); break;
case "experience": setExperience(data); break;
case "level": setLevel(data); break;
}
public void addKitCooldown(String kitName, long timeKitLastUsed) { kitCooldowns.put(kitName, timeKitLastUsed); }
public int getData(String identifier) {
return data.get(identifier);
}
private void setKills(int amount) { this.kills = amount; }
public long getTimeKitLastUsed(String kitName) { return kitCooldowns.get(kitName); }
private void setDeaths(int amount) { this.deaths = amount; }
public Map<String, Long> getKitCooldowns() { return kitCooldowns; }
private void setExperience(int amount) { this.experience = amount; }
private void setLevel(int amount) { this.level = amount; }
private int getKills() { return kills; }
private int getDeaths() { return deaths; }
private int getExperience() { return experience; }
private int getLevel() { return level; }
public Map<String, Integer> getData() { return data; }
}
@@ -1,24 +0,0 @@
package com.planetgallium.kitpvp.util;
public class PlayerEntry {
private final String username;
private int data;
public PlayerEntry(String username, int data) {
this.username = username;
this.data = data;
}
@Override
public String toString() {
return String.format("Player(%s, %s)", username, data);
}
public void setData(int newData) { this.data = newData; }
public String getUsername() { return username; }
public int getData() { return data; }
}
@@ -84,24 +84,19 @@ public class Resource extends YamlConfiguration {
}
public void addCopyDefaultExemption(String path) {
copyDefaultExemptions.add(path);
}
public void save() {
try {
super.save(file);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public String getString(String path) {
String string = super.getString(path);
public String fetchString(String path) {
String string = super.getString(path);
if (string != null) {
string = ChatColor.translateAlternateColorCodes('&',
@@ -112,7 +107,7 @@ public class Resource extends YamlConfiguration {
}
return string;
}
}
@Override
public List<String> getStringList(String path) {
@@ -1,62 +1,60 @@
package com.planetgallium.kitpvp.util;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import com.planetgallium.kitpvp.Game;
import com.planetgallium.kitpvp.api.Ability;
public class Resources {
private final Game plugin;
private final Map<String, Resource> kits;
private final Map<String, Resource> kitToResource;
private final Map<String, Resource> abilityToResource;
private final Resource config, abilities, killstreaks,
levels, menu, messages, scoreboard, signs;
public Resources(Game plugin) {
this.plugin = plugin;
this.kits = new HashMap<>();
this.kitToResource = new HashMap<>();
this.abilityToResource = new HashMap<>();
Toolkit.printToConsole("&7[&b&lKIT-PVP&7] &7Loading configuration files...");
this.config = new Resource(plugin, "config.yml");
this.abilities = new Resource(plugin, "abilities.yml");
this.killstreaks = new Resource(plugin, "killstreaks.yml");
this.levels = new Resource(plugin, "levels.yml");
this.menu = new Resource(plugin, "menu.yml");
this.messages = new Resource(plugin, "messages.yml");
this.scoreboard = new Resource(plugin, "scoreboard.yml");
this.signs = new Resource(plugin, "signs.yml");
if (!plugin.getDataFolder().exists()) {
kits.put("Fighter.yml", new Resource(plugin, "kits/Fighter.yml"));
kits.put("Archer.yml", new Resource(plugin, "kits/Archer.yml"));
kits.put("Tank.yml", new Resource(plugin, "kits/Tank.yml"));
kits.put("Soldier.yml", new Resource(plugin, "kits/Soldier.yml"));
kits.put("Bomber.yml", new Resource(plugin, "kits/Bomber.yml"));
kits.put("Kangaroo.yml", new Resource(plugin, "kits/Kangaroo.yml"));
kits.put("Warper.yml", new Resource(plugin, "kits/Warper.yml"));
kits.put("Witch.yml", new Resource(plugin, "kits/Witch.yml"));
kits.put("Ninja.yml", new Resource(plugin, "kits/Ninja.yml"));
kits.put("Thunderbolt.yml", new Resource(plugin, "kits/Thunderbolt.yml"));
kits.put("Vampire.yml", new Resource(plugin, "kits/Vampire.yml"));
kits.put("Rhino.yml", new Resource(plugin, "kits/Rhino.yml"));
kits.put("Example.yml", new Resource(plugin, "kits/Example.yml"));
kits.put("Trickster.yml", new Resource(plugin, "kits/Trickster.yml"));
}
kitToResource.put("Fighter.yml", new Resource(plugin, "kits/Fighter.yml"));
kitToResource.put("Archer.yml", new Resource(plugin, "kits/Archer.yml"));
kitToResource.put("Tank.yml", new Resource(plugin, "kits/Tank.yml"));
kitToResource.put("Soldier.yml", new Resource(plugin, "kits/Soldier.yml"));
kitToResource.put("Bomber.yml", new Resource(plugin, "kits/Bomber.yml"));
kitToResource.put("Kangaroo.yml", new Resource(plugin, "kits/Kangaroo.yml"));
kitToResource.put("Warper.yml", new Resource(plugin, "kits/Warper.yml"));
kitToResource.put("Witch.yml", new Resource(plugin, "kits/Witch.yml"));
kitToResource.put("Ninja.yml", new Resource(plugin, "kits/Ninja.yml"));
kitToResource.put("Thunderbolt.yml", new Resource(plugin, "kits/Thunderbolt.yml"));
kitToResource.put("Vampire.yml", new Resource(plugin, "kits/Vampire.yml"));
kitToResource.put("Rhino.yml", new Resource(plugin, "kits/Rhino.yml"));
kitToResource.put("Example.yml", new Resource(plugin, "kits/Example.yml"));
kitToResource.put("Trickster.yml", new Resource(plugin, "kits/Trickster.yml"));
config = new Resource(plugin, "config.yml");
abilities = new Resource(plugin, "abilities.yml");
killstreaks = new Resource(plugin, "killstreaks.yml");
levels = new Resource(plugin, "levels.yml");
menu = new Resource(plugin, "menu.yml");
messages = new Resource(plugin, "messages.yml");
scoreboard = new Resource(plugin, "scoreboard.yml");
signs = new Resource(plugin, "signs.yml");
abilityToResource.put("HealthPack.yml", new Resource(plugin, "abilities/HealthPack.yml"));
abilityToResource.put("ExampleAbility.yml", new Resource(plugin, "abilities/ExampleAbility.yml"));
abilityToResource.put("ExampleAbility2.yml", new Resource(plugin, "abilities/ExampleAbility2.yml"));
abilityToResource.put("SpeedBoost.yml", new Resource(plugin, "abilities/SpeedBoost.yml"));
abilityToResource.put("Stampede.yml", new Resource(plugin, "abilities/Stampede.yml"));
}
Toolkit.printToConsole("&7[&b&lKIT-PVP&7] &7Loading kit files...");
for (String fileName : this.getKitList(true)) {
kits.put(fileName, new Resource(plugin, "kits/" + fileName));
}
load();
}
public void load() {
@@ -89,70 +87,66 @@ public class Resources {
abilities.copyDefaults();
signs.copyDefaults();
for (String fileName : kits.keySet()) {
kits.get(fileName).load();
}
// load new kits that have been added through file system (when doing /kp reload)
for (String fileName : getKitList(true)) {
if (!kits.containsKey(fileName)) {
kits.put(fileName, new Resource(plugin, "kits/" + fileName));
// load new kits & abilities that have been added through file system (when doing /kp reload)
for (String fileName : getPluginDirectoryFiles("kits", true)) {
if (!kitToResource.containsKey(fileName) && !fileName.startsWith(".")) {
kitToResource.put(fileName, new Resource(plugin, "kits/" + fileName));
}
}
for (String fileName : getPluginDirectoryFiles("abilities", true)) {
if (!abilityToResource.containsKey(fileName) && !fileName.startsWith(".")) {
abilityToResource.put(fileName, new Resource(plugin, "abilities/" + fileName));
}
}
// Reload all kitName.yml, abilityName.yml
kitToResource.values().forEach(Resource::load);
abilityToResource.values().forEach(Resource::load);
}
public void reload() {
load();
}
public void save() {
config.save();
abilities.save();
killstreaks.save();
levels.save();
menu.save();
messages.save();
scoreboard.save();
signs.save();
for (String key : kits.keySet()) {
kits.get(key).save();
}
}
public void addResource(String fileName, Resource resource) {
kits.put(fileName, resource);
kits.get(fileName).load();
kitToResource.put(fileName, resource);
kitToResource.get(fileName).load();
}
public void removeResource(String fileName) {
kits.get(fileName).getFile().delete();
kits.remove(fileName);
kitToResource.get(fileName).getFile().delete();
kitToResource.remove(fileName);
}
public void addAbilityResource(Ability ability) {
String abilityName = ability.getName();
Resource abilityResource = new Resource(plugin, "abilities/" + abilityName + ".yml");
ability.toResource(abilityResource);
abilityToResource.put(abilityName, abilityResource);
abilityToResource.get(abilityName).load();
}
public Resource getKit(String kitName) {
if (kits.containsKey(kitName + ".yml")) {
return kits.get(kitName + ".yml");
if (kitToResource.containsKey(kitName + ".yml")) {
return kitToResource.get(kitName + ".yml");
}
return null;
}
public List<String> getKitList(boolean withFileEndings) {
File folder = new File(plugin.getDataFolder().getAbsolutePath() + "/kits");
List<String> kitList = new ArrayList<>();
public List<String> getPluginDirectoryFiles(String directoryName, boolean withFileEndings) {
File folder = new File(plugin.getDataFolder().getAbsolutePath() + "/" + directoryName);
List<String> fileList = new ArrayList<>();
if (folder.exists() && folder.list() != null) {
for (String fileName : folder.list()) {
kitList.add(withFileEndings ? fileName : fileName.split(".yml")[0]);
fileList.add(withFileEndings ? fileName : fileName.split(".yml")[0]);
}
}
return kitList;
return fileList;
}
public Resource getConfig() { return config; }
@@ -170,5 +164,7 @@ public class Resources {
public Resource getScoreboard() { return scoreboard; }
public Resource getSigns() { return signs; }
public Collection<Resource> getAbilityResources() { return abilityToResource.values(); }
}
@@ -1,9 +1,13 @@
package com.planetgallium.kitpvp.util;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import com.cryptomorin.xseries.XMaterial;
import com.cryptomorin.xseries.XPotion;
import com.cryptomorin.xseries.XSound;
import org.bukkit.*;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
@@ -17,9 +21,12 @@ import com.planetgallium.kitpvp.Game;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.potion.PotionEffectType;
public class Toolkit {
private static final Material FALLBACK_MATERIAL = Material.BEDROCK;
public static boolean inArena(World world) {
if (Game.getInstance().getResources().getConfig().contains("Arenas")) {
@@ -90,7 +97,6 @@ public class Toolkit {
if (commands == null) return;
for (String commandString : commands) {
String[] commandPhrase = commandString.split(":", 2);
if (commandPhrase.length == 1) {
@@ -104,23 +110,25 @@ public class Toolkit {
String command = commandPhrase[1];
if (sender.equals("console")) {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), addPlaceholdersIfPossible(p, command.replace("%player%", p.getName()).replace(replaceFrom, replaceTo)));
Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
replaceCommandPlaceholders(command, p, replaceFrom, replaceTo));
} else if (sender.equals("player")) {
p.performCommand(addPlaceholdersIfPossible(p, command.replace("%player%", p.getName()).replace(replaceFrom, replaceTo)));
p.performCommand(replaceCommandPlaceholders(command, p, replaceFrom, replaceTo));
} else {
Toolkit.printToConsole("&7[&b&lKIT-PVP&7] &cIncorrect command format. Please see: &fhttps://bit.ly/kp-command-format");
return;
}
}
}
private static String replaceCommandPlaceholders(String s, Player p, String replaceFrom, String replaceTo) {
String withPotentialPapiPlaceholders = addPlaceholdersIfPossible(p, s);
return withPotentialPapiPlaceholders
.replace("%player%", p.getName())
.replace("%uuid%", p.getUniqueId().toString())
.replace(replaceFrom, replaceTo);
}
public static int versionToNumber() {
@@ -148,6 +156,8 @@ public class Toolkit {
return 117;
} else if (version.contains("1.18")) {
return 118;
} else if (version.contains("1.19")) {
return 119;
}
return 500;
@@ -280,7 +290,7 @@ public class Toolkit {
public static Location getLocationFromResource(Resource resource, String path) {
return new Location(Bukkit.getWorld(resource.getString(path + ".World")),
return new Location(Bukkit.getWorld(resource.fetchString(path + ".World")),
(float) resource.getInt(path + ".X") + 0.5,
(float) resource.getInt(path + ".Y"),
(float) resource.getInt(path + ".Z") + 0.5,
@@ -334,9 +344,7 @@ public class Toolkit {
}
public static String translate(String s) {
return ChatColor.translateAlternateColorCodes('&', s.replace("%prefix%", Game.getPrefix()));
}
public static int getNextAvailable(FileConfiguration yamlConfig, String path, int limit, boolean zeroBased, int fallbackAmount) {
@@ -376,8 +384,8 @@ public class Toolkit {
public static boolean matchesConfigItem(ItemStack item, Resource resource, String path) {
ItemMeta itemMeta = item.getItemMeta();
String configItemName = resource.getString(path + ".Name");
String configItemMaterial = resource.getString(path + ".Material");
String configItemName = resource.fetchString(path + ".Name");
String configItemMaterial = resource.fetchString(path + ".Material");
if (item.getType() == XMaterial.matchXMaterial(configItemMaterial).get().parseMaterial()) {
if (itemMeta != null && itemMeta.hasDisplayName()) {
@@ -397,20 +405,16 @@ public class Toolkit {
}
public static void setMaxHealth(Player p, int amount) {
if (Toolkit.versionToNumber() >= 19) {
AttributeInstance healthAttribute = p.getAttribute(Attribute.GENERIC_MAX_HEALTH);
assert healthAttribute != null;
healthAttribute.setBaseValue(amount);
return;
}
p.setMaxHealth(amount);
}
public static int getMaxHealth(Player p) {
if (Toolkit.versionToNumber() >= 19) {
AttributeInstance healthAttribute = p.getAttribute(Attribute.GENERIC_MAX_HEALTH);
assert healthAttribute != null;
@@ -418,7 +422,54 @@ public class Toolkit {
}
return (int) p.getMaxHealth();
}
public static ItemStack safeItemStack(String materialName) {
Optional<XMaterial> materialOptional = XMaterial.matchXMaterial(materialName);
if (materialOptional.isPresent()) {
Material material = materialOptional.get().parseMaterial();
if (material != null) {
return new ItemStack(material);
}
}
printToConsole("&7[&b&lKIT-PVP&7] &cInvalid material: " + materialName);
return new ItemStack(Toolkit.FALLBACK_MATERIAL);
}
public static Sound safeSound(String soundName) {
Optional<XSound> soundOptional = XSound.matchXSound(soundName);
if (soundOptional.isPresent()) {
Sound sound = soundOptional.get().parseSound();
if (sound != null) {
return sound;
}
}
printToConsole("&7[&b&lKIT-PVP&7] &cInvalid sound: " + soundName);
return XSound.ENTITY_ENDER_DRAGON_HURT.parseSound();
}
public static PotionEffectType safePotionEffectType(String potionEffectTypeName) {
Optional<XPotion> potionOptional = XPotion.matchXPotion(potionEffectTypeName);
if (potionOptional.isPresent()) {
PotionEffectType potionEffectType = potionOptional.get().getPotionEffectType();
if (potionEffectType != null) {
return potionEffectType;
}
}
printToConsole("&7[&b&lKIT-PVP&7] &cInvalid potion effect type: " + potionEffectTypeName);
return XPotion.BLINDNESS.getPotionEffectType();
}
public static boolean itemStacksMatch(ItemStack itemA, ItemStack itemB) {
if (itemA.getType() == itemB.getType()) {
ItemMeta itemAMeta = itemA.getItemMeta();
ItemMeta itemBMeta = itemB.getItemMeta();
if (itemAMeta.hasDisplayName() && itemBMeta.hasDisplayName()) {
return itemAMeta.getDisplayName().equals(itemBMeta.getDisplayName());
}
}
return false;
}
}
@@ -1,54 +0,0 @@
package com.zp4rker.localdb;
public class Column {
public String name;
public DataType dataType;
public int limit = 0;
private Object value;
public Column(String name, DataType dataType, int limit) {
this.name = name;
this.dataType = dataType;
this.limit = limit;
}
public Column(String name, DataType dataType) {
this.name = name;
this.dataType = dataType;
this.limit = 0;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public DataType getDataType() {
return dataType;
}
public void setDataType(DataType dataType) {
this.dataType = dataType;
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
@@ -1,7 +0,0 @@
package com.zp4rker.localdb;
public enum DataType {
STRING, INTEGER, FLOAT
}
@@ -1,71 +0,0 @@
package com.zp4rker.localdb;
import org.bukkit.plugin.java.JavaPlugin;
import com.zp4rker.localdb.db.SQLite;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class Database {
private List<Table> tables = new ArrayList<>();
private SQLite sqLite;
public Database(JavaPlugin plugin, String dbName, Table table) {
this.tables.add(table);
this.sqLite = new SQLite(plugin, dbName, this);
sqLite.load();
table.setSqLite(sqLite);
}
public Database(JavaPlugin plugin, String dbName, Table table, String file) {
this.tables.add(table);
this.sqLite = new SQLite(plugin, dbName, this, file);
sqLite.load();
table.setSqLite(sqLite);
}
public List<Table> getTables() {
return tables;
}
public String getTableQuery() {
return tables.get(0).getQuery();
}
public SQLite getDB() {
return this.sqLite;
}
public Connection getConnection() {
return this.sqLite.getSQLConnection();
}
public void addTable(Table table) {
tables.add(table);
table.setSqLite(sqLite);
try {
PreparedStatement statement = this.sqLite.getSQLConnection().prepareStatement(table.getQuery());
statement.executeUpdate();
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void deleteTable(Table table) {
tables.remove(table);
try {
PreparedStatement statement = this.sqLite.getSQLConnection().prepareStatement(table.getDeleteQuery());
statement.executeUpdate();
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
@@ -1,361 +0,0 @@
package com.zp4rker.localdb;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.planetgallium.kitpvp.util.PlayerEntry;
import com.zp4rker.localdb.db.SQLite;
public class Table {
private String name;
private List<Column> columns = new ArrayList<>();
private Column primaryKey;
private SQLite sqLite;
public Table(String name, Column... columns) {
this.name = name;
this.primaryKey = columns[0];
this.columns.addAll(Arrays.asList(columns));
this.primaryKey = this.columns.get(0);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Column> getColumns() {
return columns;
}
public void setColumns(List<Column> columns) {
this.columns = columns;
}
public Column getPrimaryKey() {
return primaryKey;
}
public void setPrimaryKey(Column primaryKey) {
this.primaryKey = primaryKey;
}
private static String getStringType(DataType dataType) {
switch(dataType) {
case STRING: return "VARCHAR";
case INTEGER: return "INT";
case FLOAT: return "FLOAT";
default: return null;
}
}
public void setSqLite(SQLite sqLite) {
this.sqLite = sqLite;
}
public String getQuery() {
String query = "CREATE TABLE IF NOT EXISTS " + getName() + " (";
for (Column column : getColumns()) {
query += "`" + column.name + "` ";
query += Table.getStringType(column.dataType);
query += (column.limit > 0 ? " (" + column.limit + "), " : ", ");
}
query += "PRIMARY KEY (`" + primaryKey.getName() + "`)";
query += ");";
return query;
}
public String getDeleteQuery() {
String query = "DROP TABLE IF EXISTS " + getName();
return query;
}
public void insert(Column... columns) {
List<Column> columnList = new ArrayList<>(Arrays.asList(columns));
insert(columnList);
}
private void insert(List<Column> columns) {
if (getExact(columns.get(0)) == null) {
String query = "INSERT INTO " + getName() + " (";
for (Column column : columns) {
if (columns.indexOf(column) < columns.size() - 1) {
query += "`" + column.getName() + "`, ";
} else {
query += "`" + column.getName() + "`) ";
}
}
query += "VALUES (";
for (int i = 0; i < columns.size(); i++) {
if (i < columns.size() - 1) {
query += "?, ";
} else {
query += "?)";
}
}
query += ";";
try {
PreparedStatement s = sqLite.getSQLConnection().prepareStatement(query);
for (int i = 0; i < columns.size(); i++) {
if (columns.get(i).dataType == DataType.STRING) {
s.setString(i + 1, columns.get(i).getValue().toString());
} else if (columns.get(i).dataType == DataType.INTEGER) {
s.setInt(i + 1, Integer.parseInt(columns.get(i).getValue().toString()));
} else {
s.setFloat(i + 1, Float.parseFloat(columns.get(i).getValue().toString()));
}
}
s.executeUpdate();
s.close();
} catch (SQLException e) {
e.printStackTrace();
}
} else {
System.out.println("A row with that name already exists!");
}
}
public List<Column> getExact(Column column) {
List<Column> result = new ArrayList<>();
String query = "SELECT * FROM " + getName() + " WHERE `" + column.getName() + "`=?";
try {
PreparedStatement s = sqLite.getSQLConnection().prepareStatement(query);
if (column.dataType == DataType.STRING) {
s.setString(1, column.getValue().toString());
} else if (column.dataType == DataType.INTEGER) {
s.setInt(1, Integer.parseInt(column.getValue().toString()));
} else {
s.setFloat(1, Float.parseFloat(column.getValue().toString()));
}
ResultSet rs = s.executeQuery();
try {
for (int i = 0; i < getColumns().size(); i++) {
Column rCol = new Column(getColumns().get(i).getName(), getColumns().get(i).dataType,
getColumns().get(i).limit);
if (rCol.dataType == DataType.STRING) {
rCol.setValue(rs.getString(i + 1));
} else if (rCol.dataType == DataType.INTEGER) {
rCol.setValue(rs.getInt(i + 1));
} else {
rCol.setValue(rs.getFloat(i + 1));
}
result.add(rCol);
}
sqLite.close(s, rs);
} catch (SQLException e) {
s.close();
return null;
}
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
public List<PlayerEntry> getTopN(Column sortColumn, Column returnColumn, int n) {
// Admittedly this method is more tailored towards KitPvP leaderboards, but can be repurposed for other uses
String query = "SELECT %return_column_name%, %sort_column_name% FROM %table_name% ORDER BY %sort_column_name% DESC LIMIT %n%"
.replace("%return_column_name%", returnColumn.getName())
.replace("%table_name%", getName())
.replace("%sort_column_name%", sortColumn.getName())
.replace("%n%", String.valueOf(n));
List<PlayerEntry> topNResults = new ArrayList<>();
try {
PreparedStatement statement = sqLite.getSQLConnection().prepareStatement(query);
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
topNResults.add(new PlayerEntry(resultSet.getString(returnColumn.getName()),
resultSet.getInt(sortColumn.getName())));
}
sqLite.close(statement, resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
return topNResults;
}
public List<List<Column>> search(Column column) {
List<List<Column>> results = new ArrayList<>();
if (!column.getName().equalsIgnoreCase(primaryKey.getName())) {
String query = "SELECT * FROM " + getName() + " WHERE `" + column.getName() + "`=?";
try {
PreparedStatement s = sqLite.getSQLConnection().prepareStatement(query);
// TODO: use setStatementType
if (column.dataType == DataType.STRING) {
s.setString(1, column.getValue().toString());
} else if (column.dataType == DataType.INTEGER) {
s.setInt(1, Integer.parseInt(column.getValue().toString()));
} else {
s.setFloat(1, Float.parseFloat(column.getValue().toString()));
}
ResultSet rs = s.executeQuery();
while (rs.next()) {
List<Column> result = new ArrayList<>();
for (int i = 0; i < getColumns().size(); i++) {
Column rCol = new Column(getColumns().get(i).getName(), getColumns().get(i).dataType,
getColumns().get(i).limit);
if (getColumns().get(i).dataType == DataType.STRING) {
rCol.setValue(rs.getString(i + 1));
} else if (getColumns().get(i).dataType == DataType.INTEGER) {
rCol.setValue(rs.getInt(i + 1));
} else {
rCol.setValue(rs.getFloat(i + 1));
}
result.add(rCol);
}
results.add(result);
}
sqLite.close(s, rs);
} catch (SQLException e) {
e.printStackTrace();
}
return results;
} else {
return null;
}
}
public boolean containsColumn(Column column) {
return getExact(column) != null;
}
private void setStatementType(PreparedStatement preparedStatement, Column column) {
Object value = column.getValue();
DataType type = column.getDataType();
try {
if (type == DataType.STRING) {
preparedStatement.setString(1, value.toString());
} else if (type == DataType.INTEGER) {
preparedStatement.setInt(1, Integer.parseInt(value.toString()));
} else if (type == DataType.FLOAT) {
preparedStatement.setFloat(1, Float.parseFloat(value.toString()));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public List<List<Column>> getAll() {
List<List<Column>> results = new ArrayList<>();
String query = "SELECT * FROM " + getName();
try {
PreparedStatement s = sqLite.getSQLConnection().prepareStatement(query);
ResultSet rs = s.executeQuery();
while (rs.next()) {
List<Column> result = new ArrayList<>();
for (int i = 0; i < getColumns().size(); i++) {
Column rCol = new Column(getColumns().get(i).getName(), getColumns().get(i).dataType,
getColumns().get(i).limit);
if (getColumns().get(i).dataType == DataType.STRING) {
s.setString(1, getColumns().get(i).getValue().toString());
} else if (getColumns().get(i).dataType == DataType.INTEGER) {
s.setInt(1, Integer.parseInt(getColumns().get(i).getValue().toString()));
} else {
s.setFloat(1, Float.parseFloat(getColumns().get(i).getValue().toString()));
}
result.add(rCol);
}
results.add(result);
}
sqLite.close(s, rs);
} catch (SQLException e) {
e.printStackTrace();
}
return results;
}
public void delete(Column column) {
if (column.getName().equalsIgnoreCase(primaryKey.getName())) {
String query = "DELETE FROM " + getName() + " WHERE `" + column.getName() + "`=?";
try {
PreparedStatement s = sqLite.getSQLConnection().prepareStatement(query);
if (column.dataType == DataType.STRING) {
s.setString(1, column.getValue().toString());
} else if (column.dataType == DataType.INTEGER) {
s.setInt(1, Integer.parseInt(column.getValue().toString()));
} else {
s.setFloat(1, Float.parseFloat(column.getValue().toString()));
}
s.executeUpdate();
s.close();
} catch (SQLException e) {
e.printStackTrace();
}
} else {
System.out.println("Primary key must be used!");
}
}
public void update(Column primaryKey, Column... columns) {
List<Column> columnList = new ArrayList<>(Arrays.asList(columns));
update(primaryKey, columnList);
}
private void update(Column primaryKey, List<Column> columns) {
if (!containsKey(columns)) {
String query = "UPDATE " + getName() + " SET ";
for (Column column : columns) {
if (column.dataType == DataType.STRING) {
query += "`" + column.getName() + "`='" + column.getValue().toString() + "'";
} else {
query += "`" + column.getName() + "`=" + column.getValue().toString();
}
if (columns.indexOf(column) == columns.size() - 1) {
query += " ";
} else {
query += ", ";
}
}
query += "WHERE `" + primaryKey.getName() + "`=";
if (primaryKey.dataType == DataType.STRING) {
query += "'" + primaryKey.getValue().toString() + "'";
} else {
query += primaryKey.getValue().toString();
}
try {
PreparedStatement s = sqLite.getSQLConnection().prepareStatement(query);
s.executeUpdate();
s.close();
} catch (SQLException e) {
e.printStackTrace();
}
} else {
List<Column> newColumns = getExact(primaryKey);
for (Column column : columns) {
if (column.getName().equalsIgnoreCase(primaryKey.getName())) {
newColumns.set(0, column);
} else {
newColumns.set(columns.indexOf(column), column);
}
}
delete(primaryKey);
insert(newColumns);
}
}
private boolean containsKey(List<Column> columns) {
for (Column column : columns) {
if (column.getName().equalsIgnoreCase(primaryKey.getName())) {
return true;
}
}
return false;
}
}
@@ -1,14 +0,0 @@
package com.zp4rker.localdb.db;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.logging.Level;
public class Error {
public static void execute(JavaPlugin plugin, Exception ex){
plugin.getLogger().log(Level.SEVERE, "Couldn't execute MySQL statement: ", ex);
}
public static void close(JavaPlugin plugin, Exception ex){
plugin.getLogger().log(Level.SEVERE, "Failed to close MySQL connection: ", ex);
}
}
@@ -1,16 +0,0 @@
package com.zp4rker.localdb.db;
public class Errors {
public static String sqlConnectionExecute(){
return "Couldn't execute MySQL statement: ";
}
public static String sqlConnectionClose(){
return "Failed to close MySQL connection: ";
}
public static String noSQLConnection(){
return "Unable to retreive MYSQL connection: ";
}
public static String noTableFound(){
return "DB Error: No Table Found";
}
}
@@ -1,103 +0,0 @@
package com.zp4rker.localdb.db;
import org.bukkit.plugin.java.JavaPlugin;
import com.zp4rker.localdb.Database;
import java.io.File;
import java.io.IOException;
import java.sql.*;
import java.util.logging.Level;
public class SQLite {
private String dbName;
private String query;
private boolean inDF = true;
private String dir;
private JavaPlugin plugin;
private Connection connection;
public SQLite(JavaPlugin instance, String dbName, Database db) {
this.plugin = instance;
this.dbName = dbName;
query = db.getTableQuery();
this.connection = getSQLConnection();
}
public SQLite(JavaPlugin instance, String dbName, Database db, String directory) {
this.plugin = instance;
this.dbName = dbName;
query = db.getTableQuery();
this.inDF = false;
this.dir = directory;
this.connection = getSQLConnection();
}
public Connection getSQLConnection() {
File file;
if (inDF) {
file = new File(plugin.getDataFolder(), dbName + ".db");
plugin.getDataFolder().mkdirs();
} else {
new File(this.dir).mkdirs();
file = new File(this.dir + "/" + dbName + ".db");
}
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
plugin.getLogger().log(Level.SEVERE, "File write error: " + dbName + ".db");
}
}
try {
if (connection != null && !connection.isClosed()) {
return connection;
}
Class.forName("org.sqlite.JDBC");
connection = DriverManager.getConnection("jdbc:sqlite:" + file);
return connection;
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, "SQLite exception on initialize", ex);
} catch (ClassNotFoundException ex) {
plugin.getLogger().log(Level.SEVERE, "You need the SQLite JBDC library. Google it. Put it in /lib folder.");
}
return null;
}
public void load() {
connection = getSQLConnection();
try {
PreparedStatement s = connection.prepareStatement(query);
s.executeUpdate();
s.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void close(PreparedStatement ps, ResultSet rs) {
try {
if (ps != null)
ps.close();
if (rs != null)
rs.close();
} catch (SQLException ex) {
Error.close(plugin, ex);
}
}
public void closeConnection() {
try {
if (!(connection.isClosed())) {
connection.close();
connection = null;
} else {
connection = null;
}
} catch(Exception e) {
Error.close(plugin, e);
}
}
}
@@ -0,0 +1,18 @@
Activator:
Name: '&aAbility Item'
Material: EMERALD
Cooldown:
Cooldown: '10S'
Message:
Message: '%prefix% &7This is an example ability message.'
Sound:
Sound: NOTE_PLING
Pitch: 1
Volume: 1
Effects:
SPEED:
Amplifier: 5
Duration: 10
Commands:
- 'console: say Hi %player%, this is an example console command that can be run when you use your ability.'
- 'player: me This is an example player command that can be run when you use your ability.'
@@ -0,0 +1,5 @@
Activator:
Name: '&aSecond Ability Item &7(Unlimited custom abilities per kit!)'
Material: GOLD_INGOT
Message:
Message: '%prefix% &7KitPvP supports &aunlimited &7custom kits and each with &aunlimited &7custom abilities!'
@@ -0,0 +1,18 @@
Activator:
Name: '&aHealth Pack &7(Right Click)'
Material: ENDER_CHEST
Cooldown:
Cooldown: '30S'
Message:
Message: '%prefix% &7You have used a &bHealth Pack&7.'
Sound:
Sound: ANVIL_USE
Pitch: 1
Volume: 1
Effects:
SPEED:
Amplifier: 2
Duration: 10
REGENERATION:
Amplifier: 2
Duration: 10
@@ -0,0 +1,15 @@
Activator:
Name: '&aSpeed Boost &7(Right Click)'
Material: FEATHER
Cooldown:
Cooldown: '40S'
Message:
Message: '%prefix% &7You have used a &bSpeed Boost&7.'
Sound:
Sound: ZOMBIE_IDLE
Pitch: 1
Volume: 1
Effects:
SPEED:
Amplifier: 7
Duration: 10
+24
View File
@@ -0,0 +1,24 @@
Activator:
Name: '&aStampede &7(Right Click)'
Material: FIREWORK_STAR
Cooldown:
Cooldown: '60S'
Message:
Message: '%prefix% &7You have used your ability.'
Sound:
Sound: HORSE_ANGRY
Pitch: 0
Volume: 1
Effects:
SPEED:
Level: 3
Duration: 5
REGENERATION:
Level: 3
Duration: 5
INCREASE_DAMAGE:
Level: 2
Duration: 5
NIGHT_VISION:
Level: 1
Duration: 5
+12
View File
@@ -34,6 +34,7 @@ Combat:
ItemName: '&eReturnable Arrow'
NoSpace: '%prefix% &cYou must have at least one slot open in your inventory for you to receive your arrow for your successful shot.'
Enabled: true
Count: 2
Kill:
SoupReward:
NoSpace: '%prefix% &c%amount% soups could not be added to your full inventory.'
@@ -90,6 +91,14 @@ Commands:
Kit: false
Kits: false
Stats: false
Storage:
Type: sqlite
MySQL:
Host: 127.0.0.1
Port: 3306
Database: kitpvp
Username: root
Password: password
Arena:
ClearPotionEffectsOnJoin: true
ClearInventoryOnJoin: true
@@ -115,6 +124,9 @@ Arena:
ResetKillStreakOnLeave: true
ToSpawnOnJoin: true
DeathParticles: true
AbilitiesRequireKit: true
AddOverflowItemsOnKit: true
DropRemainingOverflowItemsOnKit: true
Other:
AutomaticallyAddKitToMenu: true
Spawn:
-26
View File
@@ -87,32 +87,6 @@ Inventory:
- '&7in a kit. You must customize'
- '&7this in the kit file.'
Material: COOKIE
Abilities:
SampleAbility:
Activator:
Name: '&aAbility Item'
Material: EMERALD
Cooldown:
Cooldown: '10S'
Message:
Message: '%prefix% &7This is an example ability message.'
Sound:
Sound: NOTE_PLING
Pitch: 1
Volume: 1
Effects:
SPEED:
Amplifier: 5
Duration: 10
Commands:
- 'console: say Hi %player%, this is an example console command that can be run when you use your ability.'
- 'player: me This is an example player command that can be run when you use your ability.'
SecondAbility:
Activator:
Name: '&aSecond Ability Item &7(Unlimited custom abilities per kit!)'
Material: GOLD_INGOT
Message:
Message: '%prefix% &7KitPvP supports &aunlimited &7custom kits and each with &aunlimited &7custom abilities!'
Commands:
- 'console: say These commands can optionally be included in your kit file'
- 'console: say to be run when the kit is selected'
+1 -21
View File
@@ -28,24 +28,4 @@ Inventory:
Material: COMPASS
Fill:
Name: '&aRegenerative Soup &7(Right Click)'
Material: MUSHROOM_SOUP
Abilities:
HealthPack:
Activator:
Name: '&aHealth Pack &7(Right Click)'
Material: ENDER_CHEST
Cooldown:
Cooldown: '30S'
Message:
Message: '%prefix% &7You have used a &bHealth Pack&7.'
Sound:
Sound: ANVIL_USE
Pitch: 1
Volume: 1
Effects:
SPEED:
Amplifier: 2
Duration: 10
REGENERATION:
Amplifier: 2
Duration: 10
Material: MUSHROOM_SOUP
+1 -27
View File
@@ -43,30 +43,4 @@ Inventory:
Material: COMPASS
Fill:
Name: '&aRegenerative Soup &7(Right Click)'
Material: MUSHROOM_SOUP
Abilities:
Stampede:
Activator:
Name: '&aStampede &7(Right Click)'
Material: FIREWORK_STAR
Cooldown:
Cooldown: '60S'
Message:
Message: '%prefix% &7You have used your ability.'
Sound:
Sound: HORSE_ANGRY
Pitch: 0
Volume: 1
Effects:
SPEED:
Level: 3
Duration: 5
REGENERATION:
Level: 3
Duration: 5
INCREASE_DAMAGE:
Level: 2
Duration: 5
NIGHT_VISION:
Level: 1
Duration: 5
Material: MUSHROOM_SOUP
+1 -18
View File
@@ -32,21 +32,4 @@ Inventory:
Effects:
SLOW:
Amplifier: 2
Duration: 100000
Abilities:
SpeedBoost:
Activator:
Name: '&aSpeed Boost &7(Right Click)'
Material: FEATHER
Cooldown:
Cooldown: '40S'
Message:
Message: '%prefix% &7You have used a &bSpeed Boost&7.'
Sound:
Sound: ZOMBIE_IDLE
Pitch: 1
Volume: 1
Effects:
SPEED:
Amplifier: 7
Duration: 10
Duration: 100000
+6
View File
@@ -24,6 +24,10 @@ Messages:
Sign: '%prefix% &7You have successfully created a sign.'
Players: '%prefix% &cThere are no other players with a kit online.'
NoKit: 'None'
PreviewMenuTitle: 'Previewing: %kit%'
PreviewMenuBackArrowItemName: '&cBack to Kits'
PreviewMenuPotionEffectsItemName: '&a&lPotion Effects'
OverflowItemsDropped: '%prefix% &b%number% &7kit items had no inventory space and were dropped on the ground.'
Error:
Player: '%prefix% &cYou must right-click on a player to activate this ability.'
Arena: '%prefix% &cNo arena exists with name %arena%.'
@@ -45,6 +49,8 @@ Messages:
PVP: '%prefix% &cPVP is not permitted in this region.'
InvalidType: '%prefix% &cInvalid type "%type%". Available types: %types%.'
InvalidNumber: '%prefix% &cInvalid number "%number%".'
OverflowItemsLost: '%prefix% &c%number% items could not fit in your inventory and were lost.'
InvalidKitName: '%prefix% &cFailed to create kit due to invalid kit name (contains +, -)'
Stats:
Message:
- '&7&m &r'
+1 -1
View File
@@ -1,7 +1,7 @@
name: KitPvP
author: Cervinakuy
main: com.planetgallium.kitpvp.Game
version: 2.2.0
version: 2.2.1
description: The ultimate all-in-one KitPvP plugin.
website: https://www.spigotmc.org/resources/27107/
softdepend: [PlaceholderAPI, WorldGuard]