Attempt at implementing NBT
This commit is contained in:
parent
12ffd41184
commit
72db20b4ae
|
@ -5,8 +5,12 @@ import net.minecraft.server.v1_15_R1.*;
|
|||
import net.seanomik.tamablefoxes.io.Config;
|
||||
import net.seanomik.tamablefoxes.versions.version_1_15.pathfinding.*;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_15_R1.persistence.CraftPersistentDataContainer;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -188,7 +192,7 @@ public class EntityTamableFox extends EntityFox {
|
|||
item.setCount(1);
|
||||
setSlot(EnumItemSlot.MAINHAND, item);
|
||||
|
||||
TamableFoxes.getPlugin().sqLiteSetterGetter.saveFox(this);
|
||||
save();
|
||||
}
|
||||
|
||||
public void setMouthItem(org.bukkit.inventory.ItemStack item) {
|
||||
|
@ -464,4 +468,26 @@ public class EntityTamableFox extends EntityFox {
|
|||
|
||||
return groupdataentity;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
NamespacedKey rootKey = new NamespacedKey(TamableFoxes.getPlugin(), "tamableFoxes");
|
||||
CraftPersistentDataContainer persistentDataContainer = getBukkitEntity().getPersistentDataContainer();
|
||||
PersistentDataContainer tamableFoxesData;
|
||||
if (persistentDataContainer.has(rootKey, PersistentDataType.TAG_CONTAINER)) {
|
||||
tamableFoxesData = persistentDataContainer.get(rootKey, PersistentDataType.TAG_CONTAINER);
|
||||
} else {
|
||||
tamableFoxesData = persistentDataContainer.getAdapterContext().newPersistentDataContainer();
|
||||
}
|
||||
|
||||
NamespacedKey ownerKey = new NamespacedKey(TamableFoxes.getPlugin(), "owner");
|
||||
NamespacedKey chosenNameKey = new NamespacedKey(TamableFoxes.getPlugin(), "chosenName");
|
||||
NamespacedKey sittingKey = new NamespacedKey(TamableFoxes.getPlugin(), "sitting");
|
||||
NamespacedKey sleepingKey = new NamespacedKey(TamableFoxes.getPlugin(), "sleeping");
|
||||
tamableFoxesData.set(ownerKey, PersistentDataType.STRING, getOwner() == null ? "none" : getOwner().getUniqueID().toString());
|
||||
tamableFoxesData.set(chosenNameKey, PersistentDataType.STRING, getChosenName());
|
||||
tamableFoxesData.set(sittingKey, PersistentDataType.BYTE, (byte) (isSitting() ? 1 : 0));
|
||||
tamableFoxesData.set(sleepingKey, PersistentDataType.BYTE, (byte) (isSleeping() ? 1 : 0));
|
||||
|
||||
persistentDataContainer.set(rootKey, PersistentDataType.TAG_CONTAINER, tamableFoxesData);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ import net.minecraft.server.v1_15_R1.*;
|
|||
import net.seanomik.tamablefoxes.versions.version_1_15.command.CommandSpawnTamableFox;
|
||||
import net.seanomik.tamablefoxes.io.Config;
|
||||
import net.seanomik.tamablefoxes.io.LanguageConfig;
|
||||
import net.seanomik.tamablefoxes.sqlite.SQLiteHandler;
|
||||
import net.seanomik.tamablefoxes.versions.version_1_15.sqlite.SQLiteSetterGetter;
|
||||
import net.wesjd.anvilgui.AnvilGUI;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.Material;
|
||||
|
@ -47,9 +45,6 @@ public final class TamableFoxes extends JavaPlugin implements Listener {
|
|||
private static TamableFoxes plugin;
|
||||
public List<EntityTamableFox> spawnedFoxes = new ArrayList<>();
|
||||
|
||||
public SQLiteSetterGetter sqLiteSetterGetter = new SQLiteSetterGetter();
|
||||
public SQLiteHandler sqLiteHandler = new SQLiteHandler();
|
||||
|
||||
private boolean versionSupported = true;
|
||||
|
||||
@Override
|
||||
|
@ -98,7 +93,6 @@ public final class TamableFoxes extends JavaPlugin implements Listener {
|
|||
getServer().getPluginManager().registerEvents(this, this);
|
||||
this.getCommand("spawntamablefox").setExecutor(new CommandSpawnTamableFox(this));
|
||||
|
||||
sqLiteSetterGetter.createTablesIfNotExist();
|
||||
this.saveDefaultConfig();
|
||||
getConfig().options().copyDefaults(true);
|
||||
saveConfig();
|
||||
|
@ -107,18 +101,18 @@ public final class TamableFoxes extends JavaPlugin implements Listener {
|
|||
@Override
|
||||
public void onDisable() {
|
||||
getServer().getConsoleSender().sendMessage(Utils.getPrefix() + ChatColor.YELLOW + LanguageConfig.getSavingFoxMessage());
|
||||
sqLiteSetterGetter.saveFoxes(spawnedFoxes);
|
||||
spawnedFoxes.forEach(EntityTamableFox::save);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onWorldSaveEvent(WorldSaveEvent event) {
|
||||
sqLiteSetterGetter.saveFoxes(spawnedFoxes);
|
||||
spawnedFoxes.forEach(EntityTamableFox::save);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onChunkLoad(ChunkLoadEvent event) {
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(this, ()-> {
|
||||
spawnedFoxes.addAll(sqLiteSetterGetter.loadFoxes(event.getChunk()));
|
||||
spawnedFoxes.addAll(Utils.loadFoxesInChunk(event.getChunk()));
|
||||
}, 5L);
|
||||
}
|
||||
|
||||
|
@ -203,8 +197,7 @@ public final class TamableFoxes extends JavaPlugin implements Listener {
|
|||
if(!text.equals("")) {
|
||||
tamableFox.setChosenName(text);
|
||||
plr.sendMessage(Utils.getPrefix() + ChatColor.GREEN + LanguageConfig.getTamingChosenPerfect(text));
|
||||
|
||||
TamableFoxes.getPlugin().sqLiteSetterGetter.saveFox(tamableFox);
|
||||
tamableFox.save();
|
||||
}
|
||||
|
||||
return AnvilGUI.Response.close();
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
package net.seanomik.tamablefoxes;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import net.minecraft.server.v1_15_R1.EntityLiving;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_15_R1.persistence.CraftPersistentDataContainer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Utils {
|
||||
|
||||
|
@ -63,14 +66,14 @@ public class Utils {
|
|||
try {
|
||||
Class<?> innerClass = getPrivateInnerClass(outer, innerName);
|
||||
|
||||
Object[] argObjects = new Object[args.size()+1];
|
||||
Class<?>[] argClasses = new Class<?>[argTypes.size()+1];
|
||||
Object[] argObjects = new Object[args.size() + 1];
|
||||
Class<?>[] argClasses = new Class<?>[argTypes.size() + 1];
|
||||
|
||||
// Needed due to how List#toArray() converts the classes to objects
|
||||
for (int i = 0; i < argClasses.length; i++) {
|
||||
if (i == argClasses.length-1) continue;
|
||||
argObjects[i+1] = args.get(i);
|
||||
argClasses[i+1] = argTypes.get(i);
|
||||
if (i == argClasses.length - 1) continue;
|
||||
argObjects[i + 1] = args.get(i);
|
||||
argClasses[i + 1] = argTypes.get(i);
|
||||
}
|
||||
argObjects[0] = outerObject;
|
||||
argClasses[0] = outer;
|
||||
|
@ -110,4 +113,50 @@ public class Utils {
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<EntityTamableFox> loadFoxesInChunk(Chunk chunk) {
|
||||
return Arrays.stream(chunk.getEntities()).filter(Utils::isTamableFox)
|
||||
.map(entity -> (EntityTamableFox) ((CraftEntity) entity).getHandle())
|
||||
.peek(tamableFox -> {
|
||||
NamespacedKey rootKey = new NamespacedKey(TamableFoxes.getPlugin(), "tamableFoxes");
|
||||
CraftPersistentDataContainer persistentDataContainer = tamableFox.getBukkitEntity().getPersistentDataContainer();
|
||||
if (persistentDataContainer.has(rootKey, PersistentDataType.TAG_CONTAINER)) {
|
||||
PersistentDataContainer tamableFoxesData = persistentDataContainer.get(rootKey, PersistentDataType.TAG_CONTAINER);
|
||||
NamespacedKey ownerKey = new NamespacedKey(TamableFoxes.getPlugin(), "owner");
|
||||
NamespacedKey chosenNameKey = new NamespacedKey(TamableFoxes.getPlugin(), "chosenName");
|
||||
NamespacedKey sittingKey = new NamespacedKey(TamableFoxes.getPlugin(), "sitting");
|
||||
NamespacedKey sleepingKey = new NamespacedKey(TamableFoxes.getPlugin(), "sleeping");
|
||||
|
||||
String ownerUUIDString = tamableFoxesData.get(ownerKey, PersistentDataType.STRING);
|
||||
String chosenName = tamableFoxesData.get(chosenNameKey, PersistentDataType.STRING);
|
||||
boolean sitting = ((byte) 1) == tamableFoxesData.get(sittingKey, PersistentDataType.BYTE);
|
||||
boolean sleeping = ((byte) 1) == tamableFoxesData.get(sleepingKey, PersistentDataType.BYTE);
|
||||
|
||||
boolean tamed = false;
|
||||
if (!ownerUUIDString.equals("none")) {
|
||||
tamed = true;
|
||||
|
||||
OfflinePlayer owner = TamableFoxes.getPlugin().getServer().getOfflinePlayer(UUID.fromString(ownerUUIDString));
|
||||
if (owner.isOnline()) {
|
||||
EntityLiving livingOwner = (EntityLiving) ((CraftEntity) owner).getHandle();
|
||||
tamableFox.setOwner(livingOwner);
|
||||
}
|
||||
|
||||
tamableFox.setOwnerUUID(owner.getUniqueId());
|
||||
tamableFox.setTamed(true);
|
||||
tamableFox.setChosenName(chosenName);
|
||||
}
|
||||
|
||||
if (sitting && tamed) {
|
||||
tamableFox.setHardSitting(true);
|
||||
} else if (sleeping) {
|
||||
tamableFox.setSleeping(true);
|
||||
} else { // Avoid the foxes getting stuck sitting down.
|
||||
tamableFox.setSitting(false);
|
||||
tamableFox.setSleeping(false);
|
||||
}
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
package net.seanomik.tamablefoxes.sqlite;
|
||||
|
||||
import net.seanomik.tamablefoxes.TamableFoxes;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
public class SQLiteHandler {
|
||||
private Connection connection;
|
||||
|
||||
public void connect() {
|
||||
try {
|
||||
String url = "jdbc:sqlite:" + TamableFoxes.getPlugin().getDataFolder() + "/foxes.db";
|
||||
connection = DriverManager.getConnection(url);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public Connection getConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
public void closeConnection() {
|
||||
try {
|
||||
connection.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void newConnection() {
|
||||
try {
|
||||
connection.close();
|
||||
connect();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void setConnection(Connection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
}
|
|
@ -41,7 +41,7 @@ public class CommandSpawnTamableFox implements TabExecutor {
|
|||
case "red":
|
||||
try {
|
||||
EntityTamableFox fox = plugin.spawnTamableFox(player.getLocation(), EntityFox.Type.RED);
|
||||
plugin.sqLiteSetterGetter.saveFox(fox);
|
||||
fox.save();
|
||||
|
||||
player.sendMessage(Utils.getPrefix() + ChatColor.RESET + LanguageConfig.getSpawnedFoxMessage(EntityFox.Type.RED));
|
||||
} catch (Exception e) {
|
||||
|
@ -52,7 +52,7 @@ public class CommandSpawnTamableFox implements TabExecutor {
|
|||
case "snow":
|
||||
try {
|
||||
EntityTamableFox spawnedFox = plugin.spawnTamableFox(player.getLocation(), EntityFox.Type.SNOW);
|
||||
plugin.sqLiteSetterGetter.saveFox(spawnedFox);
|
||||
spawnedFox.save();
|
||||
|
||||
player.sendMessage(Utils.getPrefix() + ChatColor.RESET + LanguageConfig.getSpawnedFoxMessage(EntityFox.Type.SNOW));
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -1,200 +0,0 @@
|
|||
package net.seanomik.tamablefoxes.versions.version_1_15.sqlite;
|
||||
|
||||
import net.minecraft.server.v1_15_R1.EntityLiving;
|
||||
import net.seanomik.tamablefoxes.EntityTamableFox;
|
||||
import net.seanomik.tamablefoxes.TamableFoxes;
|
||||
import net.seanomik.tamablefoxes.Utils;
|
||||
import net.seanomik.tamablefoxes.io.LanguageConfig;
|
||||
import net.seanomik.tamablefoxes.sqlite.SQLiteHandler;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftEntity;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
|
||||
// @TODO: Use try-with-resource instead of try-catch-finally
|
||||
|
||||
public class SQLiteSetterGetter {
|
||||
public static TamableFoxes plugin;
|
||||
public static SQLiteHandler sqLiteHandler;
|
||||
|
||||
public void createTablesIfNotExist() {
|
||||
plugin = TamableFoxes.getPlugin(TamableFoxes.class);
|
||||
sqLiteHandler = plugin.sqLiteHandler;
|
||||
|
||||
String foxesTable =
|
||||
"CREATE TABLE IF NOT EXISTS `foxes` ( " +
|
||||
"`ENTITY_UUID` TEXT PRIMARY KEY , " +
|
||||
"`OWNER_UUID` TEXT NOT NULL , " +
|
||||
"`NAME` TEXT, " +
|
||||
"`SITTING` INTEGER NOT NULL , " +
|
||||
"`SLEEPING` INTEGER NOT NULL);";
|
||||
|
||||
try {
|
||||
sqLiteHandler.connect();
|
||||
// Create previous bans table
|
||||
DatabaseMetaData dbm = sqLiteHandler.getConnection().getMetaData();
|
||||
ResultSet tables = dbm.getTables(null, null, "foxes", null);
|
||||
if (!tables.next()) {
|
||||
PreparedStatement statement = sqLiteHandler.getConnection().prepareStatement(foxesTable);
|
||||
statement.executeUpdate();
|
||||
|
||||
plugin.getServer().getConsoleSender().sendMessage(Utils.getPrefix() + ChatColor.GREEN + LanguageConfig.getCreatedSQLDatabase());
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (sqLiteHandler.getConnection() != null) {
|
||||
sqLiteHandler.closeConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void saveFox(EntityTamableFox fox) {
|
||||
plugin = TamableFoxes.getPlugin(TamableFoxes.class);
|
||||
|
||||
// If the fox is null or not alive, delete it from the database
|
||||
if (fox == null || !fox.isAlive()) {
|
||||
removeFox(fox);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
sqLiteHandler.connect();
|
||||
|
||||
PreparedStatement statement = sqLiteHandler.getConnection().prepareStatement("INSERT INTO foxes (ENTITY_UUID,OWNER_UUID,NAME,SITTING,SLEEPING) VALUES (?,?,?,?,?)");
|
||||
|
||||
// If the database does contain this fox, then change the statement to an update statement instead of insert.
|
||||
PreparedStatement hasFoxStatement = sqLiteHandler.getConnection().prepareStatement("SELECT * FROM foxes WHERE ENTITY_UUID=?");
|
||||
hasFoxStatement.setString(1, fox.getUniqueID().toString());
|
||||
ResultSet results = hasFoxStatement.executeQuery();
|
||||
if (results.next()) {
|
||||
statement = sqLiteHandler.getConnection().prepareStatement("UPDATE foxes SET OWNER_UUID=?, NAME=?, SITTING=?, SLEEPING=? WHERE ENTITY_UUID='" + fox.getUniqueID().toString() + "'");
|
||||
statement.setString(1, (fox.getOwner() == null) ? "none" : fox.getOwner().getUniqueID().toString());
|
||||
statement.setString(2, fox.getChosenName());
|
||||
statement.setInt(3, (fox.isSitting()) ? 1 : 0);
|
||||
statement.setInt(4, (fox.isSleeping()) ? 1 : 0);
|
||||
} else {
|
||||
statement.setString(1, fox.getUniqueID().toString());
|
||||
statement.setString(2, (fox.getOwner() == null) ? "none" : fox.getOwner().getUniqueID().toString());
|
||||
statement.setString(3, fox.getChosenName());
|
||||
statement.setInt(4, (fox.isSitting()) ? 1 : 0);
|
||||
statement.setInt(5, (fox.isSleeping()) ? 1 : 0);
|
||||
}
|
||||
|
||||
statement.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (sqLiteHandler.getConnection() != null) {
|
||||
sqLiteHandler.closeConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void saveFoxes(List<EntityTamableFox> foxes) { // @TODO: Optimize?
|
||||
if (foxes == null || foxes.size() == 0) return;
|
||||
|
||||
for (EntityTamableFox fox : foxes) {
|
||||
saveFox(fox);
|
||||
}
|
||||
}
|
||||
|
||||
public List<EntityTamableFox> loadFoxes(Chunk chunk) {
|
||||
plugin = TamableFoxes.getPlugin(TamableFoxes.class);
|
||||
|
||||
// If there are no foxes then don't even start
|
||||
List<EntityTamableFox> foxesInChunk = new ArrayList<>();
|
||||
for (Entity entity : chunk.getEntities()) {
|
||||
if (Utils.isTamableFox(entity)) {
|
||||
foxesInChunk.add((EntityTamableFox) ((CraftEntity) entity).getHandle());
|
||||
}
|
||||
}
|
||||
|
||||
if (foxesInChunk.size() == 0) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
try {
|
||||
sqLiteHandler.connect();
|
||||
|
||||
List<EntityTamableFox> spawnedFoxes = new ArrayList<>();
|
||||
|
||||
for (EntityTamableFox tamableFox : foxesInChunk) {
|
||||
PreparedStatement statement = sqLiteHandler.getConnection().prepareStatement("SELECT * FROM foxes WHERE ENTITY_UUID=?");
|
||||
statement.setString(1, tamableFox.getUniqueID().toString());
|
||||
ResultSet results = statement.executeQuery();
|
||||
|
||||
if (results.next()) {
|
||||
String ownerUUIDString = results.getString("OWNER_UUID");
|
||||
String name = results.getString("NAME");
|
||||
boolean sitting = results.getInt("SITTING") == 1;
|
||||
boolean sleeping = results.getInt("SLEEPING") == 1;
|
||||
|
||||
boolean tamed = false;
|
||||
if (!ownerUUIDString.equals("none")) {
|
||||
tamed = true;
|
||||
|
||||
OfflinePlayer owner = plugin.getServer().getOfflinePlayer(UUID.fromString(ownerUUIDString));
|
||||
if (owner.isOnline()) {
|
||||
EntityLiving livingOwner = (EntityLiving) ((CraftEntity) owner).getHandle();
|
||||
tamableFox.setOwner(livingOwner);
|
||||
}
|
||||
|
||||
tamableFox.setOwnerUUID(owner.getUniqueId());
|
||||
tamableFox.setTamed(true);
|
||||
tamableFox.setChosenName(name);
|
||||
}
|
||||
|
||||
if (sitting && tamed) {
|
||||
tamableFox.setHardSitting(true);
|
||||
} else if (sleeping) {
|
||||
tamableFox.setSleeping(true);
|
||||
} else { // Avoid the foxes getting stuck sitting down.
|
||||
tamableFox.setSitting(false);
|
||||
tamableFox.setSleeping(false);
|
||||
}
|
||||
|
||||
|
||||
spawnedFoxes.add(tamableFox);
|
||||
}
|
||||
}
|
||||
|
||||
return spawnedFoxes;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (sqLiteHandler.getConnection() != null) {
|
||||
sqLiteHandler.closeConnection();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void removeFox(UUID uuid) {
|
||||
plugin = TamableFoxes.getPlugin(TamableFoxes.class);
|
||||
try {
|
||||
sqLiteHandler.connect();
|
||||
|
||||
PreparedStatement statement = sqLiteHandler.getConnection().prepareStatement("DELETE FROM foxes WHERE ENTITY_UUID='" + uuid.toString() + "'");
|
||||
statement.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (sqLiteHandler.getConnection() != null) {
|
||||
sqLiteHandler.closeConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeFox(EntityTamableFox fox) {
|
||||
removeFox(fox.getUniqueID());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue