mirror of
https://github.com/DRE2N/DungeonsXL.git
synced 2024-11-28 21:48:43 +01:00
#39: Copy files and load worlds asynchronously
This commit is contained in:
parent
3778009785
commit
27afe9b1fd
@ -32,6 +32,7 @@ DungeonsXL also provides custom game mechanics to make these worlds interesting.
|
|||||||
* A powerful API: [Read more...](../../wiki/api-tutorial)
|
* A powerful API: [Read more...](../../wiki/api-tutorial)
|
||||||
* Different game types allow you to use your maps dynamically for different purposes. [Read more...](../../wiki/game-types)
|
* Different game types allow you to use your maps dynamically for different purposes. [Read more...](../../wiki/game-types)
|
||||||
* Announcements sothat users can join the next match easily. [Read more...](../../wiki/announcements)
|
* Announcements sothat users can join the next match easily. [Read more...](../../wiki/announcements)
|
||||||
|
* Great performance due to a custom, asynchronous world loading and creation method and several other performance tweaks
|
||||||
* ...and many more!
|
* ...and many more!
|
||||||
|
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ If you want to learn how to use DungeonsXL step by step, please have a look at t
|
|||||||
DungeonsXL works with 1.7.8 and higher. However, support for 1.10.x / 1.9.x has a higher priority than support for 1.8.x and lower. Some cosmetic features require the Spigot API and will therefore not work with CraftBukkit.
|
DungeonsXL works with 1.7.8 and higher. However, support for 1.10.x / 1.9.x has a higher priority than support for 1.8.x and lower. Some cosmetic features require the Spigot API and will therefore not work with CraftBukkit.
|
||||||
|
|
||||||
Older versions of DungeonsXL support versions since Minecraft 1.3.x, but of course, they are completely unsupported.
|
Older versions of DungeonsXL support versions since Minecraft 1.3.x, but of course, they are completely unsupported.
|
||||||
* [1.7.8-1.10](../../tree/master)
|
* [1.7.8-1.10.2](../../tree/master)
|
||||||
* [1.7.5](../../tree/50f772d14281bfe278dba2559d1758cc459c1a30)
|
* [1.7.5](../../tree/50f772d14281bfe278dba2559d1758cc459c1a30)
|
||||||
* [1.7.2](../../tree/eccf82b7335dfb0723e3cd37a57df1a968ea7842)
|
* [1.7.2](../../tree/eccf82b7335dfb0723e3cd37a57df1a968ea7842)
|
||||||
* [1.6.4](../../tree/780145cf783ea76fe1bfee04cf89216bd4f92e1d)
|
* [1.6.4](../../tree/780145cf783ea76fe1bfee04cf89216bd4f92e1d)
|
||||||
|
7
pom.xml
7
pom.xml
@ -70,7 +70,7 @@
|
|||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.spigotmc</groupId>
|
<groupId>org.spigotmc</groupId>
|
||||||
<artifactId>spigot-api</artifactId>
|
<artifactId>spigot</artifactId>
|
||||||
<version>1.10.2-R0.1-SNAPSHOT</version>
|
<version>1.10.2-R0.1-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
@ -121,11 +121,6 @@
|
|||||||
<artifactId>BetonQuest</artifactId>
|
<artifactId>BetonQuest</artifactId>
|
||||||
<version>1.8.5</version>
|
<version>1.8.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.boydti</groupId>
|
|
||||||
<artifactId>fawe-api</artifactId>
|
|
||||||
<version>3.5.0-dev</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
|
@ -188,6 +188,7 @@ public class DungeonsXL extends BRPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
|
mainConfig.setTweaksEnabled(false);
|
||||||
// Save
|
// Save
|
||||||
saveData();
|
saveData();
|
||||||
messageConfig.save();
|
messageConfig.save();
|
||||||
|
@ -97,7 +97,7 @@ public class CreateCommand extends BRCommand {
|
|||||||
MessageUtil.log(plugin, DMessages.LOG_WORLD_GENERATION_FINISHED.getMessage());
|
MessageUtil.log(plugin, DMessages.LOG_WORLD_GENERATION_FINISHED.getMessage());
|
||||||
|
|
||||||
// Tp Player
|
// Tp Player
|
||||||
new DEditPlayer(player, editWorld.getWorld());
|
DEditPlayer.create(player, editWorld);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ public class EditCommand extends BRCommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
new DEditPlayer(player, editWorld.getWorld());
|
DEditPlayer.create(player, editWorld);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ public class EnterCommand extends BRCommand {
|
|||||||
joining.sendMessage(DMessages.CMD_ENTER_SUCCESS.getMessage(joining.getName(), targetName));
|
joining.sendMessage(DMessages.CMD_ENTER_SUCCESS.getMessage(joining.getName(), targetName));
|
||||||
|
|
||||||
for (Player player : joining.getPlayers()) {
|
for (Player player : joining.getPlayers()) {
|
||||||
new DGamePlayer(player, game.getWorld()).ready();
|
DGamePlayer.create(player, game.getWorld(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ import java.io.File;
|
|||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Frank Baumann, Daniel Saukel
|
* @author Frank Baumann, Daniel Saukel
|
||||||
@ -47,8 +48,8 @@ public class ImportCommand extends BRCommand {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onExecute(String[] args, CommandSender sender) {
|
public void onExecute(String[] args, CommandSender sender) {
|
||||||
File target = new File(DungeonsXL.MAPS, args[1]);
|
final File target = new File(DungeonsXL.MAPS, args[1]);
|
||||||
File source = new File(Bukkit.getWorldContainer(), args[1]);
|
final File source = new File(Bukkit.getWorldContainer(), args[1]);
|
||||||
|
|
||||||
if (!source.exists()) {
|
if (!source.exists()) {
|
||||||
MessageUtil.sendMessage(sender, DMessages.ERROR_NO_SUCH_MAP.getMessage(args[1]));
|
MessageUtil.sendMessage(sender, DMessages.ERROR_NO_SUCH_MAP.getMessage(args[1]));
|
||||||
@ -68,10 +69,19 @@ public class ImportCommand extends BRCommand {
|
|||||||
MessageUtil.log(plugin, DMessages.LOG_NEW_MAP.getMessage());
|
MessageUtil.log(plugin, DMessages.LOG_NEW_MAP.getMessage());
|
||||||
MessageUtil.log(plugin, DMessages.LOG_IMPORT_WORLD.getMessage());
|
MessageUtil.log(plugin, DMessages.LOG_IMPORT_WORLD.getMessage());
|
||||||
|
|
||||||
|
if (!plugin.getMainConfig().areTweaksEnabled()) {
|
||||||
FileUtil.copyDirectory(source, target, new String[]{"playerdata", "stats"});
|
FileUtil.copyDirectory(source, target, new String[]{"playerdata", "stats"});
|
||||||
|
|
||||||
plugin.getDWorlds().addResource(new DResourceWorld(plugin.getDWorlds(), args[1]));
|
} else {
|
||||||
|
new BukkitRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
FileUtil.copyDirectory(source, target, new String[]{"playerdata", "stats"});
|
||||||
|
}
|
||||||
|
}.runTaskAsynchronously(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.getDWorlds().addResource(new DResourceWorld(plugin.getDWorlds(), args[1]));
|
||||||
MessageUtil.sendMessage(sender, DMessages.CMD_IMPORT_SUCCESS.getMessage(args[1]));
|
MessageUtil.sendMessage(sender, DMessages.CMD_IMPORT_SUCCESS.getMessage(args[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,8 +58,10 @@ public class ListCommand extends BRCommand {
|
|||||||
}
|
}
|
||||||
ArrayList<String> mapList = new ArrayList<>();
|
ArrayList<String> mapList = new ArrayList<>();
|
||||||
for (File file : DungeonsXL.MAPS.listFiles()) {
|
for (File file : DungeonsXL.MAPS.listFiles()) {
|
||||||
|
if (!file.equals(DWorlds.RAW)) {
|
||||||
mapList.add(file.getName());
|
mapList.add(file.getName());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ArrayList<String> loadedList = new ArrayList<>();
|
ArrayList<String> loadedList = new ArrayList<>();
|
||||||
for (DEditWorld editWorld : worlds.getEditWorlds()) {
|
for (DEditWorld editWorld : worlds.getEditWorlds()) {
|
||||||
loadedList.add(editWorld.getWorld().getWorldFolder().getName());
|
loadedList.add(editWorld.getWorld().getWorldFolder().getName());
|
||||||
|
@ -145,12 +145,12 @@ public class PlayCommand extends BRCommand {
|
|||||||
|
|
||||||
if (dGroup.getGameWorld().getLobbyLocation() == null) {
|
if (dGroup.getGameWorld().getLobbyLocation() == null) {
|
||||||
for (Player groupPlayer : dGroup.getPlayers()) {
|
for (Player groupPlayer : dGroup.getPlayers()) {
|
||||||
new DGamePlayer(groupPlayer, dGroup.getGameWorld());
|
DGamePlayer.create(groupPlayer, dGroup.getGameWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
for (Player groupPlayer : dGroup.getPlayers()) {
|
for (Player groupPlayer : dGroup.getPlayers()) {
|
||||||
new DGamePlayer(groupPlayer, dGroup.getGameWorld());
|
DGamePlayer.create(groupPlayer, dGroup.getGameWorld());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import io.github.dre2n.commons.command.BRCommand;
|
|||||||
import io.github.dre2n.commons.util.messageutil.MessageUtil;
|
import io.github.dre2n.commons.util.messageutil.MessageUtil;
|
||||||
import io.github.dre2n.dungeonsxl.DungeonsXL;
|
import io.github.dre2n.dungeonsxl.DungeonsXL;
|
||||||
import io.github.dre2n.dungeonsxl.config.DMessages;
|
import io.github.dre2n.dungeonsxl.config.DMessages;
|
||||||
|
import io.github.dre2n.dungeonsxl.config.MainConfig;
|
||||||
import io.github.dre2n.dungeonsxl.config.MainConfig.BackupMode;
|
import io.github.dre2n.dungeonsxl.config.MainConfig.BackupMode;
|
||||||
import io.github.dre2n.dungeonsxl.player.DPermissions;
|
import io.github.dre2n.dungeonsxl.player.DPermissions;
|
||||||
import io.github.dre2n.dungeonsxl.world.DEditWorld;
|
import io.github.dre2n.dungeonsxl.world.DEditWorld;
|
||||||
@ -32,6 +33,7 @@ import org.bukkit.entity.Player;
|
|||||||
public class SaveCommand extends BRCommand {
|
public class SaveCommand extends BRCommand {
|
||||||
|
|
||||||
DungeonsXL plugin = DungeonsXL.getInstance();
|
DungeonsXL plugin = DungeonsXL.getInstance();
|
||||||
|
MainConfig mainConfig = plugin.getMainConfig();
|
||||||
|
|
||||||
public SaveCommand() {
|
public SaveCommand() {
|
||||||
setCommand("save");
|
setCommand("save");
|
||||||
@ -47,9 +49,9 @@ public class SaveCommand extends BRCommand {
|
|||||||
Player player = (Player) sender;
|
Player player = (Player) sender;
|
||||||
DEditWorld editWorld = DEditWorld.getByWorld(player.getWorld());
|
DEditWorld editWorld = DEditWorld.getByWorld(player.getWorld());
|
||||||
if (editWorld != null) {
|
if (editWorld != null) {
|
||||||
BackupMode backupMode = plugin.getMainConfig().getBackupMode();
|
BackupMode backupMode = mainConfig.getBackupMode();
|
||||||
if (backupMode == BackupMode.ON_SAVE || backupMode == BackupMode.ON_DISABLE_AND_SAVE) {
|
if (backupMode == BackupMode.ON_SAVE || backupMode == BackupMode.ON_DISABLE_AND_SAVE) {
|
||||||
editWorld.getResource().backup(false);
|
editWorld.getResource().backup(mainConfig.areTweaksEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
editWorld.save();
|
editWorld.save();
|
||||||
|
@ -38,7 +38,7 @@ public class MainConfig extends BRConfig {
|
|||||||
NEVER
|
NEVER
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final int CONFIG_VERSION = 10;
|
public static final int CONFIG_VERSION = 11;
|
||||||
|
|
||||||
private String language = "english";
|
private String language = "english";
|
||||||
private boolean enableEconomy = false;
|
private boolean enableEconomy = false;
|
||||||
@ -65,7 +65,10 @@ public class MainConfig extends BRConfig {
|
|||||||
/* Misc */
|
/* Misc */
|
||||||
private boolean sendFloorTitle = true;
|
private boolean sendFloorTitle = true;
|
||||||
private Map<String, Object> externalMobProviders = new HashMap<>();
|
private Map<String, Object> externalMobProviders = new HashMap<>();
|
||||||
|
|
||||||
|
/* Performance */
|
||||||
private int maxInstances = 10;
|
private int maxInstances = 10;
|
||||||
|
private boolean tweaksEnabled = false;
|
||||||
|
|
||||||
/* Secure Mode */
|
/* Secure Mode */
|
||||||
private boolean secureModeEnabled = false;
|
private boolean secureModeEnabled = false;
|
||||||
@ -247,6 +250,21 @@ public class MainConfig extends BRConfig {
|
|||||||
this.maxInstances = maxInstances;
|
this.maxInstances = maxInstances;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return if the performance tweaks are enabled
|
||||||
|
*/
|
||||||
|
public boolean areTweaksEnabled() {
|
||||||
|
return tweaksEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param enabled
|
||||||
|
* if the performance tweaks are enabled
|
||||||
|
*/
|
||||||
|
public void setTweaksEnabled(boolean enabled) {
|
||||||
|
tweaksEnabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return if the secure mode is enabled
|
* @return if the secure mode is enabled
|
||||||
*/
|
*/
|
||||||
@ -390,6 +408,10 @@ public class MainConfig extends BRConfig {
|
|||||||
config.set("maxInstances", maxInstances);
|
config.set("maxInstances", maxInstances);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!config.contains("tweaksEnabled")) {
|
||||||
|
config.set("tweaksEnabled", tweaksEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
if (!config.contains("secureMode.enabled")) {
|
if (!config.contains("secureMode.enabled")) {
|
||||||
config.set("secureMode.enabled", secureModeEnabled);
|
config.set("secureMode.enabled", secureModeEnabled);
|
||||||
}
|
}
|
||||||
@ -473,6 +495,10 @@ public class MainConfig extends BRConfig {
|
|||||||
maxInstances = config.getInt("maxInstances");
|
maxInstances = config.getInt("maxInstances");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.contains("tweaksEnabled")) {
|
||||||
|
tweaksEnabled = config.getBoolean("tweaksEnabled");
|
||||||
|
}
|
||||||
|
|
||||||
if (config.contains("secureMode.enabled")) {
|
if (config.contains("secureMode.enabled")) {
|
||||||
secureModeEnabled = config.getBoolean("secureMode.enabled");
|
secureModeEnabled = config.getBoolean("secureMode.enabled");
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,8 @@ public class SignData {
|
|||||||
* the DEditWorld where the signs are
|
* the DEditWorld where the signs are
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public void deserializeSigns(DEditWorld editWorld) throws IOException {
|
public void deserializeSigns(DEditWorld editWorld) {
|
||||||
|
try {
|
||||||
ObjectInputStream os = new ObjectInputStream(new FileInputStream(file));
|
ObjectInputStream os = new ObjectInputStream(new FileInputStream(file));
|
||||||
int length = os.readInt();
|
int length = os.readInt();
|
||||||
|
|
||||||
@ -78,6 +79,10 @@ public class SignData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} catch (IOException exception) {
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,7 +93,8 @@ public class SignData {
|
|||||||
* @return a Set of all DSign blocks
|
* @return a Set of all DSign blocks
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public void deserializeSigns(DGameWorld gameWorld) throws IOException {
|
public void deserializeSigns(DGameWorld gameWorld) {
|
||||||
|
try {
|
||||||
ObjectInputStream os = new ObjectInputStream(new FileInputStream(file));
|
ObjectInputStream os = new ObjectInputStream(new FileInputStream(file));
|
||||||
|
|
||||||
int length = os.readInt();
|
int length = os.readInt();
|
||||||
@ -105,6 +111,10 @@ public class SignData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
os.close();
|
os.close();
|
||||||
|
|
||||||
|
} catch (IOException exception) {
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -114,7 +124,7 @@ public class SignData {
|
|||||||
* the DEditWorld that contains the signs to serialize
|
* the DEditWorld that contains the signs to serialize
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public void serializeSigns(DEditWorld editWorld) throws IOException {
|
public void serializeSigns(DEditWorld editWorld) {
|
||||||
serializeSigns(editWorld.getSigns());
|
serializeSigns(editWorld.getSigns());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +135,8 @@ public class SignData {
|
|||||||
* the signs to serialize
|
* the signs to serialize
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public void serializeSigns(List<Block> signs) throws IOException {
|
public void serializeSigns(List<Block> signs) {
|
||||||
|
try {
|
||||||
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
|
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
|
||||||
out.writeInt(signs.size());
|
out.writeInt(signs.size());
|
||||||
|
|
||||||
@ -136,6 +147,10 @@ public class SignData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
out.close();
|
out.close();
|
||||||
|
|
||||||
|
} catch (IOException exception) {
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,7 @@ public class DPortal extends GlobalProtection {
|
|||||||
dGroup.setGameWorld(target);
|
dGroup.setGameWorld(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
new DGamePlayer(player, target);
|
DGamePlayer.create(player, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -554,7 +554,7 @@ public class PlayerListener implements Listener {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
new DGamePlayer(player, dGroup.getGameWorld());
|
DGamePlayer.create(player, dGroup.getGameWorld());
|
||||||
plugin.debug.end("PlayerListener#onJoin", true);
|
plugin.debug.end("PlayerListener#onJoin", true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import io.github.dre2n.commons.util.messageutil.MessageUtil;
|
|||||||
import io.github.dre2n.commons.util.playerutil.PlayerUtil;
|
import io.github.dre2n.commons.util.playerutil.PlayerUtil;
|
||||||
import io.github.dre2n.dungeonsxl.config.DMessages;
|
import io.github.dre2n.dungeonsxl.config.DMessages;
|
||||||
import io.github.dre2n.dungeonsxl.event.dplayer.DPlayerUpdateEvent;
|
import io.github.dre2n.dungeonsxl.event.dplayer.DPlayerUpdateEvent;
|
||||||
|
import io.github.dre2n.dungeonsxl.task.CreateDInstancePlayerTask;
|
||||||
import io.github.dre2n.dungeonsxl.world.DEditWorld;
|
import io.github.dre2n.dungeonsxl.world.DEditWorld;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
@ -40,19 +41,15 @@ public class DEditPlayer extends DInstancePlayer {
|
|||||||
|
|
||||||
private String[] linesCopy;
|
private String[] linesCopy;
|
||||||
|
|
||||||
public DEditPlayer(DGlobalPlayer player, DEditWorld world) {
|
public DEditPlayer(Player player, DEditWorld world) {
|
||||||
this(player.getPlayer(), world.getWorld());
|
super(player, world.getWorld());
|
||||||
}
|
|
||||||
|
|
||||||
public DEditPlayer(Player player, World world) {
|
|
||||||
super(player, world);
|
|
||||||
|
|
||||||
player.setGameMode(GameMode.CREATIVE);
|
player.setGameMode(GameMode.CREATIVE);
|
||||||
clearPlayerData();
|
clearPlayerData();
|
||||||
|
|
||||||
Location teleport = DEditWorld.getByWorld(world).getLobbyLocation();
|
Location teleport = world.getLobbyLocation();
|
||||||
if (teleport == null) {
|
if (teleport == null) {
|
||||||
PlayerUtil.secureTeleport(player, world.getSpawnLocation());
|
PlayerUtil.secureTeleport(player, world.getWorld().getSpawnLocation());
|
||||||
} else {
|
} else {
|
||||||
PlayerUtil.secureTeleport(player, teleport);
|
PlayerUtil.secureTeleport(player, teleport);
|
||||||
}
|
}
|
||||||
@ -65,6 +62,16 @@ public class DEditPlayer extends DInstancePlayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param player
|
||||||
|
* the represented Player
|
||||||
|
* @param editWorld
|
||||||
|
* the player's EditWorld
|
||||||
|
*/
|
||||||
|
public static void create(Player player, DEditWorld editWorld) {
|
||||||
|
new CreateDInstancePlayerTask(player, editWorld).runTaskTimer(plugin, 0L, 5L);
|
||||||
|
}
|
||||||
|
|
||||||
/* Getters and setters */
|
/* Getters and setters */
|
||||||
/**
|
/**
|
||||||
* @return the linesCopy
|
* @return the linesCopy
|
||||||
|
@ -33,9 +33,11 @@ import io.github.dre2n.dungeonsxl.game.GameRules;
|
|||||||
import io.github.dre2n.dungeonsxl.game.GameType;
|
import io.github.dre2n.dungeonsxl.game.GameType;
|
||||||
import io.github.dre2n.dungeonsxl.game.GameTypeDefault;
|
import io.github.dre2n.dungeonsxl.game.GameTypeDefault;
|
||||||
import io.github.dre2n.dungeonsxl.mob.DMob;
|
import io.github.dre2n.dungeonsxl.mob.DMob;
|
||||||
|
import static io.github.dre2n.dungeonsxl.player.DGlobalPlayer.plugin;
|
||||||
import io.github.dre2n.dungeonsxl.requirement.Requirement;
|
import io.github.dre2n.dungeonsxl.requirement.Requirement;
|
||||||
import io.github.dre2n.dungeonsxl.reward.DLootInventory;
|
import io.github.dre2n.dungeonsxl.reward.DLootInventory;
|
||||||
import io.github.dre2n.dungeonsxl.reward.Reward;
|
import io.github.dre2n.dungeonsxl.reward.Reward;
|
||||||
|
import io.github.dre2n.dungeonsxl.task.CreateDInstancePlayerTask;
|
||||||
import io.github.dre2n.dungeonsxl.trigger.DistanceTrigger;
|
import io.github.dre2n.dungeonsxl.trigger.DistanceTrigger;
|
||||||
import io.github.dre2n.dungeonsxl.world.DGameWorld;
|
import io.github.dre2n.dungeonsxl.world.DGameWorld;
|
||||||
import io.github.dre2n.dungeonsxl.world.DResourceWorld;
|
import io.github.dre2n.dungeonsxl.world.DResourceWorld;
|
||||||
@ -54,6 +56,7 @@ import org.bukkit.entity.Wolf;
|
|||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.potion.PotionEffect;
|
import org.bukkit.potion.PotionEffect;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a player in a DGameWorld.
|
* Represents a player in a DGameWorld.
|
||||||
@ -77,15 +80,11 @@ public class DGamePlayer extends DInstancePlayer {
|
|||||||
private int initialLives = -1;
|
private int initialLives = -1;
|
||||||
private int lives;
|
private int lives;
|
||||||
|
|
||||||
public DGamePlayer(Player player, DGameWorld gameWorld) {
|
public DGamePlayer(Player player, DGameWorld world) {
|
||||||
this(player, gameWorld.getWorld());
|
super(player, world.getWorld());
|
||||||
}
|
|
||||||
|
|
||||||
public DGamePlayer(Player player, World world) {
|
|
||||||
super(player, world);
|
|
||||||
|
|
||||||
plugin.debug.start("DGamePlayer#init");
|
plugin.debug.start("DGamePlayer#init");
|
||||||
Game game = Game.getByWorld(world);
|
Game game = Game.getByGameWorld(world);
|
||||||
if (game == null) {
|
if (game == null) {
|
||||||
game = new Game(DGroup.getByPlayer(player));
|
game = new Game(DGroup.getByPlayer(player));
|
||||||
}
|
}
|
||||||
@ -104,15 +103,37 @@ public class DGamePlayer extends DInstancePlayer {
|
|||||||
initialLives = rules.getInitialLives();
|
initialLives = rules.getInitialLives();
|
||||||
lives = initialLives;
|
lives = initialLives;
|
||||||
|
|
||||||
Location teleport = DGameWorld.getByWorld(world).getLobbyLocation();
|
Location teleport = world.getLobbyLocation();
|
||||||
if (teleport == null) {
|
if (teleport == null) {
|
||||||
PlayerUtil.secureTeleport(player, world.getSpawnLocation());
|
PlayerUtil.secureTeleport(player, world.getWorld().getSpawnLocation());
|
||||||
} else {
|
} else {
|
||||||
PlayerUtil.secureTeleport(player, teleport);
|
PlayerUtil.secureTeleport(player, teleport);
|
||||||
}
|
}
|
||||||
plugin.debug.end("DGamePlayer#init", true);
|
plugin.debug.end("DGamePlayer#init", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param player
|
||||||
|
* the represented Player
|
||||||
|
* @param gameWorld
|
||||||
|
* the player's GameWorld
|
||||||
|
*/
|
||||||
|
public static void create(Player player, DGameWorld gameWorld) {
|
||||||
|
create(player, gameWorld, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param player
|
||||||
|
* the represented Player
|
||||||
|
* @param gameWorld
|
||||||
|
* the player's GameWorld
|
||||||
|
* @param ready
|
||||||
|
* if the player will be ready from the beginning
|
||||||
|
*/
|
||||||
|
public static void create(Player player, DGameWorld gameWorld, boolean ready) {
|
||||||
|
new CreateDInstancePlayerTask(player, gameWorld, ready).runTaskTimer(plugin, 0L, 5L);
|
||||||
|
}
|
||||||
|
|
||||||
/* Getters and setters */
|
/* Getters and setters */
|
||||||
/**
|
/**
|
||||||
* @param player
|
* @param player
|
||||||
|
@ -31,7 +31,7 @@ public abstract class DInstancePlayer extends DGlobalPlayer {
|
|||||||
private World world;
|
private World world;
|
||||||
private boolean inDungeonChat = false;
|
private boolean inDungeonChat = false;
|
||||||
|
|
||||||
public DInstancePlayer(Player player, World world) {
|
DInstancePlayer(Player player, World world) {
|
||||||
super(player);
|
super(player);
|
||||||
|
|
||||||
double health = player.getHealth();
|
double health = player.getHealth();
|
||||||
|
@ -87,7 +87,7 @@ public class AnnouncerStartGameTask extends BukkitRunnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Player player : game.getPlayers()) {
|
for (Player player : game.getPlayers()) {
|
||||||
new DGamePlayer(player, game.getWorld());
|
DGamePlayer.create(player, game.getWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
announcer.endStartTask();
|
announcer.endStartTask();
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2012-2016 Frank Baumann
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package io.github.dre2n.dungeonsxl.task;
|
||||||
|
|
||||||
|
import io.github.dre2n.commons.util.messageutil.MessageUtil;
|
||||||
|
import io.github.dre2n.dungeonsxl.player.DEditPlayer;
|
||||||
|
import io.github.dre2n.dungeonsxl.player.DGamePlayer;
|
||||||
|
import io.github.dre2n.dungeonsxl.world.DEditWorld;
|
||||||
|
import io.github.dre2n.dungeonsxl.world.DGameWorld;
|
||||||
|
import io.github.dre2n.dungeonsxl.world.DInstanceWorld;
|
||||||
|
import java.util.UUID;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Daniel Saukel
|
||||||
|
*/
|
||||||
|
public class CreateDInstancePlayerTask extends BukkitRunnable {
|
||||||
|
|
||||||
|
public static final String BAR = "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588";
|
||||||
|
|
||||||
|
private UUID player;
|
||||||
|
private DInstanceWorld instance;
|
||||||
|
private boolean ready;
|
||||||
|
|
||||||
|
private int i = 12;
|
||||||
|
|
||||||
|
public CreateDInstancePlayerTask(Player player, DInstanceWorld instance) {
|
||||||
|
this.player = player.getUniqueId();
|
||||||
|
this.instance = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateDInstancePlayerTask(Player player, DInstanceWorld instance, boolean ready) {
|
||||||
|
this.player = player.getUniqueId();
|
||||||
|
this.instance = instance;
|
||||||
|
this.ready = ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Player player = Bukkit.getPlayer(this.player);
|
||||||
|
if (player == null || !player.isOnline()) {
|
||||||
|
cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instance.exists()) {
|
||||||
|
if (instance instanceof DGameWorld) {
|
||||||
|
DGamePlayer gamePlayer = new DGamePlayer(player, (DGameWorld) instance);
|
||||||
|
if (ready) {
|
||||||
|
gamePlayer.ready();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (instance instanceof DEditWorld) {
|
||||||
|
new DEditPlayer(player, (DEditWorld) instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder bar = new StringBuilder(BAR);
|
||||||
|
int pos = i;
|
||||||
|
if (bar.length() - pos < 0) {
|
||||||
|
pos = bar.length();
|
||||||
|
}
|
||||||
|
bar.insert(bar.length() - pos, ChatColor.GREEN.toString());
|
||||||
|
|
||||||
|
pos = i - 2;
|
||||||
|
if (pos > 0) {
|
||||||
|
bar.insert(bar.length() - pos, ChatColor.DARK_RED.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageUtil.sendActionBarMessage(player, ChatColor.DARK_RED + bar.toString());
|
||||||
|
|
||||||
|
i--;
|
||||||
|
if (i == 0) {
|
||||||
|
i = 12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -32,18 +32,22 @@ public class WorldUnloadTask extends BukkitRunnable {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
for (DGameWorld gameWorld : plugin.getDWorlds().getGameWorlds()) {
|
for (DGameWorld gameWorld : plugin.getDWorlds().getGameWorlds()) {
|
||||||
|
if (gameWorld.exists()) {
|
||||||
if (gameWorld.getWorld().getPlayers().isEmpty()) {
|
if (gameWorld.getWorld().getPlayers().isEmpty()) {
|
||||||
if (DGamePlayer.getByWorld(gameWorld.getWorld()).isEmpty()) {
|
if (DGamePlayer.getByWorld(gameWorld.getWorld()).isEmpty()) {
|
||||||
gameWorld.delete();
|
gameWorld.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (DEditWorld editWorld : plugin.getDWorlds().getEditWorlds()) {
|
for (DEditWorld editWorld : plugin.getDWorlds().getEditWorlds()) {
|
||||||
|
if (editWorld.exists()) {
|
||||||
if (editWorld.getWorld().getPlayers().isEmpty()) {
|
if (editWorld.getWorld().getPlayers().isEmpty()) {
|
||||||
editWorld.delete(true);
|
editWorld.delete(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
206
src/main/java/io/github/dre2n/dungeonsxl/util/WorldLoader.java
Normal file
206
src/main/java/io/github/dre2n/dungeonsxl/util/WorldLoader.java
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2012-2016 Frank Baumann
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package io.github.dre2n.dungeonsxl.util;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import net.minecraft.server.v1_10_R1.BlockPosition;
|
||||||
|
import net.minecraft.server.v1_10_R1.Convertable;
|
||||||
|
import net.minecraft.server.v1_10_R1.EntityTracker;
|
||||||
|
import net.minecraft.server.v1_10_R1.EnumDifficulty;
|
||||||
|
import net.minecraft.server.v1_10_R1.EnumGamemode;
|
||||||
|
import net.minecraft.server.v1_10_R1.IDataManager;
|
||||||
|
import net.minecraft.server.v1_10_R1.IProgressUpdate;
|
||||||
|
import net.minecraft.server.v1_10_R1.MinecraftServer;
|
||||||
|
import net.minecraft.server.v1_10_R1.ServerNBTManager;
|
||||||
|
import net.minecraft.server.v1_10_R1.WorldData;
|
||||||
|
import net.minecraft.server.v1_10_R1.WorldLoaderServer;
|
||||||
|
import net.minecraft.server.v1_10_R1.WorldManager;
|
||||||
|
import net.minecraft.server.v1_10_R1.WorldServer;
|
||||||
|
import net.minecraft.server.v1_10_R1.WorldSettings;
|
||||||
|
import net.minecraft.server.v1_10_R1.WorldType;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.WorldCreator;
|
||||||
|
import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
|
||||||
|
import org.bukkit.craftbukkit.v1_10_R1.CraftWorld;
|
||||||
|
import org.bukkit.event.world.WorldInitEvent;
|
||||||
|
import org.bukkit.event.world.WorldLoadEvent;
|
||||||
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
import org.bukkit.plugin.PluginManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A custom thread safe world loader.
|
||||||
|
*
|
||||||
|
* @author Daniel Saukel
|
||||||
|
*/
|
||||||
|
public class WorldLoader {
|
||||||
|
|
||||||
|
static MinecraftServer console;
|
||||||
|
static CraftServer server = ((CraftServer) Bukkit.getServer());
|
||||||
|
static Map<String, World> worlds;
|
||||||
|
static PluginManager pluginManager = Bukkit.getPluginManager();
|
||||||
|
static File worldContainer = Bukkit.getWorldContainer();
|
||||||
|
static Logger logger = Bukkit.getLogger();
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
Field fConsole = CraftServer.class.getDeclaredField("console");
|
||||||
|
fConsole.setAccessible(true);
|
||||||
|
console = (MinecraftServer) fConsole.get(server);
|
||||||
|
|
||||||
|
Field fWorlds = CraftServer.class.getDeclaredField("worlds");
|
||||||
|
fWorlds.setAccessible(true);
|
||||||
|
worlds = (Map<String, World>) fWorlds.get(server);
|
||||||
|
|
||||||
|
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException exception) {
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param creator
|
||||||
|
* the WorldCreator which stores the information to create the new world
|
||||||
|
* @return
|
||||||
|
* the new World
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public static World createWorld(WorldCreator creator) {
|
||||||
|
String name = creator.name();
|
||||||
|
ChunkGenerator generator = creator.generator();
|
||||||
|
File folder = new File(worldContainer, name);
|
||||||
|
World world = Bukkit.getWorld(name);
|
||||||
|
WorldType type = WorldType.getType(creator.type().getName());
|
||||||
|
boolean generateStructures = creator.generateStructures();
|
||||||
|
|
||||||
|
if (world != null) {
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((folder.exists()) && (!folder.isDirectory())) {
|
||||||
|
throw new IllegalArgumentException("File exists with the name '" + name + "' and isn't a folder");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (generator == null) {
|
||||||
|
generator = server.getGenerator(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Convertable converter = new WorldLoaderServer(worldContainer, server.getHandle().getServer().getDataConverterManager());
|
||||||
|
if (converter.isConvertable(name)) {
|
||||||
|
logger.info("Converting world '" + name + "'");
|
||||||
|
converter.convert(name, new IProgressUpdate() {
|
||||||
|
private long b = System.currentTimeMillis();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void a(String s) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void a(int i) {
|
||||||
|
if (System.currentTimeMillis() - this.b >= 1000L) {
|
||||||
|
this.b = System.currentTimeMillis();
|
||||||
|
MinecraftServer.LOGGER.info("Converting... " + i + "%");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void c(String s) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
int dimension = CraftWorld.CUSTOM_DIMENSION_OFFSET + console.worlds.size();
|
||||||
|
boolean used = false;
|
||||||
|
do {
|
||||||
|
for (WorldServer server : console.worlds) {
|
||||||
|
used = server.dimension == dimension;
|
||||||
|
if (used) {
|
||||||
|
dimension++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (used);
|
||||||
|
boolean hardcore = false;
|
||||||
|
|
||||||
|
IDataManager sdm = new ServerNBTManager(worldContainer, name, true, server.getHandle().getServer().getDataConverterManager());
|
||||||
|
WorldData worlddata = sdm.getWorldData();
|
||||||
|
WorldSettings worldSettings = null;
|
||||||
|
if (worlddata == null) {
|
||||||
|
worldSettings = new WorldSettings(creator.seed(), EnumGamemode.getById(server.getDefaultGameMode().getValue()), generateStructures, hardcore, type);
|
||||||
|
worldSettings.setGeneratorSettings(creator.generatorSettings());
|
||||||
|
worlddata = new WorldData(worldSettings, name);
|
||||||
|
}
|
||||||
|
worlddata.checkName(name); // CraftBukkit - Migration did not rewrite the level.dat; This forces 1.8 to take the last loaded world as respawn (in this case the end)
|
||||||
|
WorldServer internal = (WorldServer) new WorldServer(console, sdm, worlddata, dimension, console.methodProfiler, creator.environment(), generator).b();
|
||||||
|
|
||||||
|
if (!(worlds.containsKey(name.toLowerCase(java.util.Locale.ENGLISH)))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (worldSettings != null) {
|
||||||
|
internal.a(worldSettings);
|
||||||
|
}
|
||||||
|
internal.scoreboard = server.getScoreboardManager().getMainScoreboard().getHandle();
|
||||||
|
|
||||||
|
internal.tracker = new EntityTracker(internal);
|
||||||
|
internal.addIWorldAccess(new WorldManager(console, internal));
|
||||||
|
internal.worldData.setDifficulty(EnumDifficulty.EASY);
|
||||||
|
internal.setSpawnFlags(true, true);
|
||||||
|
console.worlds.add(internal);
|
||||||
|
|
||||||
|
if (generator != null) {
|
||||||
|
internal.getWorld().getPopulators().addAll(generator.getDefaultPopulators(internal.getWorld()));
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginManager.callEvent(new WorldInitEvent(internal.getWorld()));
|
||||||
|
logger.info("Preparing start region for level " + (console.worlds.size() - 1) + " (Seed: " + internal.getSeed() + ")");
|
||||||
|
|
||||||
|
if (internal.getWorld().getKeepSpawnInMemory()) {
|
||||||
|
short short1 = 196;
|
||||||
|
long i = System.currentTimeMillis();
|
||||||
|
for (int j = -short1; j <= short1; j += 16) {
|
||||||
|
for (int k = -short1; k <= short1; k += 16) {
|
||||||
|
long l = System.currentTimeMillis();
|
||||||
|
|
||||||
|
if (l < i) {
|
||||||
|
i = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l > i + 1000L) {
|
||||||
|
int i1 = (short1 * 2 + 1) * (short1 * 2 + 1);
|
||||||
|
int j1 = (j + short1) * (short1 * 2 + 1) + k + 1;
|
||||||
|
|
||||||
|
logger.info("Preparing spawn area for " + name + ", " + (j1 * 100 / i1) + "%");
|
||||||
|
i = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockPosition chunkcoordinates = internal.getSpawn();
|
||||||
|
try {
|
||||||
|
internal.getChunkProviderServer().getChunkAt(chunkcoordinates.getX() + j >> 4, chunkcoordinates.getZ() + k >> 4);
|
||||||
|
} catch (Exception exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pluginManager.callEvent(new WorldLoadEvent(internal.getWorld()));
|
||||||
|
return internal.getWorld();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -28,6 +28,7 @@ import org.bukkit.World;
|
|||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.Sign;
|
import org.bukkit.block.Sign;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Frank Baumann, Daniel Saukel
|
* @author Frank Baumann, Daniel Saukel
|
||||||
@ -43,7 +44,10 @@ public class DEditWorld extends DInstanceWorld {
|
|||||||
|
|
||||||
DEditWorld(DResourceWorld resourceWorld, File folder, World world, int id) {
|
DEditWorld(DResourceWorld resourceWorld, File folder, World world, int id) {
|
||||||
super(resourceWorld, folder, world, id);
|
super(resourceWorld, folder, world, id);
|
||||||
generateIdFile();
|
}
|
||||||
|
|
||||||
|
DEditWorld(DResourceWorld resourceWorld, File folder, int id) {
|
||||||
|
this(resourceWorld, folder, null, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Getters and setters */
|
/* Getters and setters */
|
||||||
@ -113,14 +117,21 @@ public class DEditWorld extends DInstanceWorld {
|
|||||||
|
|
||||||
getWorld().save();
|
getWorld().save();
|
||||||
|
|
||||||
|
if (!plugin.getMainConfig().areTweaksEnabled()) {
|
||||||
FileUtil.copyDirectory(getFolder(), getResource().getFolder(), DungeonsXL.EXCLUDED_FILES);
|
FileUtil.copyDirectory(getFolder(), getResource().getFolder(), DungeonsXL.EXCLUDED_FILES);
|
||||||
FileUtil.deleteUnusedFiles(getResource().getFolder());
|
FileUtil.deleteUnusedFiles(getResource().getFolder());
|
||||||
|
|
||||||
try {
|
} else {
|
||||||
getResource().getSignData().serializeSigns(signs);
|
new BukkitRunnable() {
|
||||||
} catch (IOException exception) {
|
@Override
|
||||||
exception.printStackTrace();
|
public void run() {
|
||||||
|
FileUtil.copyDirectory(getFolder(), getResource().getFolder(), DungeonsXL.EXCLUDED_FILES);
|
||||||
|
FileUtil.deleteUnusedFiles(getResource().getFolder());
|
||||||
}
|
}
|
||||||
|
}.runTaskAsynchronously(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
getResource().getSignData().serializeSigns(signs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -134,7 +145,8 @@ public class DEditWorld extends DInstanceWorld {
|
|||||||
* @param save
|
* @param save
|
||||||
* whether this world should be saved
|
* whether this world should be saved
|
||||||
*/
|
*/
|
||||||
public void delete(boolean save) {
|
public void delete(final boolean save) {
|
||||||
|
plugin.debug.start("DEditWorld#delete");
|
||||||
EditWorldUnloadEvent event = new EditWorldUnloadEvent(this, true);
|
EditWorldUnloadEvent event = new EditWorldUnloadEvent(this, true);
|
||||||
plugin.getServer().getPluginManager().callEvent(event);
|
plugin.getServer().getPluginManager().callEvent(event);
|
||||||
|
|
||||||
@ -142,26 +154,42 @@ public class DEditWorld extends DInstanceWorld {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
worlds.getInstances().remove(this);
|
|
||||||
for (Player player : getWorld().getPlayers()) {
|
for (Player player : getWorld().getPlayers()) {
|
||||||
DEditPlayer dPlayer = DEditPlayer.getByPlayer(player);
|
DEditPlayer dPlayer = DEditPlayer.getByPlayer(player);
|
||||||
dPlayer.leave();
|
dPlayer.leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!plugin.getMainConfig().areTweaksEnabled()) {
|
||||||
if (save) {
|
if (save) {
|
||||||
plugin.getServer().unloadWorld(getWorld(), true);
|
plugin.getServer().unloadWorld(getWorld(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileUtil.copyDirectory(getFolder(), getResource().getFolder(), DungeonsXL.EXCLUDED_FILES);
|
FileUtil.copyDirectory(getFolder(), getResource().getFolder(), DungeonsXL.EXCLUDED_FILES);
|
||||||
FileUtil.deleteUnusedFiles(getResource().getFolder());
|
FileUtil.deleteUnusedFiles(getResource().getFolder());
|
||||||
|
|
||||||
if (!save) {
|
if (!save) {
|
||||||
plugin.getServer().unloadWorld(getWorld(), true);
|
plugin.getServer().unloadWorld(getWorld(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileUtil.removeDirectory(getFolder());
|
FileUtil.removeDirectory(getFolder());
|
||||||
|
|
||||||
worlds.removeInstance(this);
|
worlds.removeInstance(this);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
final DEditWorld editWorld = this;
|
||||||
|
new BukkitRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (save) {
|
||||||
|
plugin.getServer().unloadWorld(getWorld(), true);
|
||||||
|
}
|
||||||
|
FileUtil.copyDirectory(getFolder(), getResource().getFolder(), DungeonsXL.EXCLUDED_FILES);
|
||||||
|
FileUtil.deleteUnusedFiles(getResource().getFolder());
|
||||||
|
if (!save) {
|
||||||
|
plugin.getServer().unloadWorld(getWorld(), true);
|
||||||
|
}
|
||||||
|
FileUtil.removeDirectory(getFolder());
|
||||||
|
worlds.removeInstance(editWorld);
|
||||||
|
}
|
||||||
|
}.runTaskAsynchronously(plugin);
|
||||||
|
}
|
||||||
|
plugin.debug.end("DEditWorld#delete", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Statics */
|
/* Statics */
|
||||||
|
@ -49,6 +49,7 @@ import org.bukkit.entity.EntityType;
|
|||||||
import org.bukkit.entity.LivingEntity;
|
import org.bukkit.entity.LivingEntity;
|
||||||
import org.bukkit.entity.Spider;
|
import org.bukkit.entity.Spider;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Frank Baumann, Milan Albrecht, Daniel Saukel
|
* @author Frank Baumann, Milan Albrecht, Daniel Saukel
|
||||||
@ -73,6 +74,10 @@ public class DGameWorld extends DInstanceWorld {
|
|||||||
super(resourceWorld, folder, world, id);
|
super(resourceWorld, folder, world, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DGameWorld(DResourceWorld resourceWorld, File folder, int id) {
|
||||||
|
this(resourceWorld, folder, null, id);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return
|
* @return
|
||||||
* the Game connected to the DGameWorld
|
* the Game connected to the DGameWorld
|
||||||
@ -354,7 +359,6 @@ public class DGameWorld extends DInstanceWorld {
|
|||||||
* Set up the instance for the game
|
* Set up the instance for the game
|
||||||
*/
|
*/
|
||||||
public void startGame() {
|
public void startGame() {
|
||||||
plugin.debug.start("DGameWorld#startGame");
|
|
||||||
GameWorldStartGameEvent event = new GameWorldStartGameEvent(this, getGame());
|
GameWorldStartGameEvent event = new GameWorldStartGameEvent(this, getGame());
|
||||||
plugin.getServer().getPluginManager().callEvent(event);
|
plugin.getServer().getPluginManager().callEvent(event);
|
||||||
|
|
||||||
@ -387,7 +391,6 @@ public class DGameWorld extends DInstanceWorld {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
plugin.debug.end("DGameWorld#startGame", true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -403,11 +406,22 @@ public class DGameWorld extends DInstanceWorld {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.getDWorlds().getInstances().remove(this);
|
if (!plugin.getMainConfig().areTweaksEnabled()) {
|
||||||
plugin.getServer().unloadWorld(getWorld(), true);
|
plugin.getServer().unloadWorld(getWorld(), false);
|
||||||
FileUtil.removeDirectory(getFolder());
|
FileUtil.removeDirectory(getFolder());
|
||||||
|
|
||||||
worlds.removeInstance(this);
|
worlds.removeInstance(this);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
final DGameWorld gameWorld = this;
|
||||||
|
new BukkitRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
plugin.getServer().unloadWorld(getWorld(), false);
|
||||||
|
FileUtil.removeDirectory(getFolder());
|
||||||
|
worlds.removeInstance(gameWorld);
|
||||||
|
}
|
||||||
|
}.runTaskAsynchronously(plugin);
|
||||||
|
}
|
||||||
plugin.debug.end("DGameWorld#delete", true);
|
plugin.debug.end("DGameWorld#delete", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ public abstract class DInstanceWorld {
|
|||||||
|
|
||||||
private DResourceWorld resourceWorld;
|
private DResourceWorld resourceWorld;
|
||||||
private File folder;
|
private File folder;
|
||||||
private World world;
|
World world;
|
||||||
private int id;
|
private int id;
|
||||||
private Location lobby;
|
private Location lobby;
|
||||||
|
|
||||||
@ -83,6 +83,13 @@ public abstract class DInstanceWorld {
|
|||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return false if this instance does not have a world, yet
|
||||||
|
*/
|
||||||
|
public boolean exists() {
|
||||||
|
return world != null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the unique ID
|
* @return the unique ID
|
||||||
*/
|
*/
|
||||||
|
@ -20,13 +20,14 @@ import io.github.dre2n.commons.util.FileUtil;
|
|||||||
import io.github.dre2n.dungeonsxl.DungeonsXL;
|
import io.github.dre2n.dungeonsxl.DungeonsXL;
|
||||||
import io.github.dre2n.dungeonsxl.config.SignData;
|
import io.github.dre2n.dungeonsxl.config.SignData;
|
||||||
import io.github.dre2n.dungeonsxl.config.WorldConfig;
|
import io.github.dre2n.dungeonsxl.config.WorldConfig;
|
||||||
|
import io.github.dre2n.dungeonsxl.event.editworld.EditWorldGenerateEvent;
|
||||||
import io.github.dre2n.dungeonsxl.player.DEditPlayer;
|
import io.github.dre2n.dungeonsxl.player.DEditPlayer;
|
||||||
import io.github.dre2n.dungeonsxl.task.BackupResourceTask;
|
import io.github.dre2n.dungeonsxl.task.BackupResourceTask;
|
||||||
|
import io.github.dre2n.dungeonsxl.util.WorldLoader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.WorldCreator;
|
import org.bukkit.WorldCreator;
|
||||||
import org.bukkit.WorldType;
|
import org.bukkit.WorldType;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
@ -187,32 +188,47 @@ public class DResourceWorld {
|
|||||||
* whether the instance is a DGameWorld
|
* whether the instance is a DGameWorld
|
||||||
* @return an instance of this world
|
* @return an instance of this world
|
||||||
*/
|
*/
|
||||||
public DInstanceWorld instantiate(boolean game) {
|
public DInstanceWorld instantiate(final boolean game) {
|
||||||
plugin.debug.start("DResourceWorld#instantiate");
|
plugin.debug.start("DResourceWorld#instantiate");
|
||||||
int id = worlds.generateId();
|
int id = worlds.generateId();
|
||||||
String name = worlds.generateName(game);
|
String name = worlds.generateName(game);
|
||||||
File instanceFolder = new File(Bukkit.getWorldContainer(), name);
|
final File instanceFolder = new File(Bukkit.getWorldContainer(), name);
|
||||||
FileUtil.copyDirectory(folder, instanceFolder, DungeonsXL.EXCLUDED_FILES);
|
|
||||||
|
|
||||||
if (Bukkit.getWorld(name) != null) {
|
if (Bukkit.getWorld(name) != null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
World world = plugin.getServer().createWorld(WorldCreator.name(name));
|
final DInstanceWorld instance = game ? new DGameWorld(this, instanceFolder, id) : new DEditWorld(this, instanceFolder, id);
|
||||||
|
|
||||||
|
if (!plugin.getMainConfig().areTweaksEnabled()) {
|
||||||
|
FileUtil.copyDirectory(folder, instanceFolder, DungeonsXL.EXCLUDED_FILES);
|
||||||
|
instance.world = plugin.getServer().createWorld(WorldCreator.name(name));
|
||||||
|
|
||||||
DInstanceWorld instance = null;
|
|
||||||
try {
|
|
||||||
if (game) {
|
if (game) {
|
||||||
instance = new DGameWorld(this, instanceFolder, world, id);
|
|
||||||
signData.deserializeSigns((DGameWorld) instance);
|
signData.deserializeSigns((DGameWorld) instance);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
instance = new DEditWorld(this, instanceFolder, world, id);
|
|
||||||
signData.deserializeSigns((DEditWorld) instance);
|
signData.deserializeSigns((DEditWorld) instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException exception) {
|
} else {
|
||||||
exception.printStackTrace();
|
new BukkitRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
FileUtil.copyDirectory(folder, instanceFolder, DungeonsXL.EXCLUDED_FILES);
|
||||||
|
instance.world = WorldLoader.createWorld(WorldCreator.name(instanceFolder.getName()));
|
||||||
|
|
||||||
|
new BukkitRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (game) {
|
||||||
|
signData.deserializeSigns((DGameWorld) instance);
|
||||||
|
} else {
|
||||||
|
signData.deserializeSigns((DEditWorld) instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.runTask(plugin);
|
||||||
|
}
|
||||||
|
}.runTaskAsynchronously(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.debug.end("DResourceWorld#instantiate", true);
|
plugin.debug.end("DResourceWorld#instantiate", true);
|
||||||
@ -240,23 +256,34 @@ public class DResourceWorld {
|
|||||||
*/
|
*/
|
||||||
public DEditWorld generate() {
|
public DEditWorld generate() {
|
||||||
plugin.debug.start("DResourceWorld#generate");
|
plugin.debug.start("DResourceWorld#generate");
|
||||||
String name = worlds.generateName(false);
|
final String name = worlds.generateName(false);
|
||||||
WorldCreator creator = WorldCreator.name(name);
|
int id = worlds.generateId();
|
||||||
|
final File folder = new File(Bukkit.getWorldContainer(), name);
|
||||||
|
final WorldCreator creator = new WorldCreator(name);
|
||||||
creator.type(WorldType.FLAT);
|
creator.type(WorldType.FLAT);
|
||||||
creator.generateStructures(false);
|
creator.generateStructures(false);
|
||||||
|
|
||||||
/*EditWorldGenerateEvent event = new EditWorldGenerateEvent(this);
|
final DEditWorld editWorld = new DEditWorld(this, folder, id);
|
||||||
|
|
||||||
|
EditWorldGenerateEvent event = new EditWorldGenerateEvent(editWorld);
|
||||||
plugin.getServer().getPluginManager().callEvent(event);
|
plugin.getServer().getPluginManager().callEvent(event);
|
||||||
|
|
||||||
if (event.isCancelled()) {
|
if (event.isCancelled()) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
int id = worlds.generateId();
|
|
||||||
File folder = new File(Bukkit.getWorldContainer(), name);
|
|
||||||
World world = plugin.getServer().createWorld(creator);
|
|
||||||
|
|
||||||
DEditWorld editWorld = new DEditWorld(this, folder, world, id);
|
if (!plugin.getMainConfig().areTweaksEnabled()) {
|
||||||
|
editWorld.world = creator.createWorld();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
new BukkitRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
FileUtil.copyDirectory(DWorlds.RAW, folder, DungeonsXL.EXCLUDED_FILES);
|
||||||
|
editWorld.generateIdFile();
|
||||||
|
editWorld.world = WorldLoader.createWorld(creator);
|
||||||
|
}
|
||||||
|
}.runTaskAsynchronously(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
plugin.debug.end("DResourceWorld#generate", true);
|
plugin.debug.end("DResourceWorld#generate", true);
|
||||||
return editWorld;
|
return editWorld;
|
||||||
|
@ -19,11 +19,15 @@ package io.github.dre2n.dungeonsxl.world;
|
|||||||
import io.github.dre2n.commons.util.FileUtil;
|
import io.github.dre2n.commons.util.FileUtil;
|
||||||
import io.github.dre2n.commons.util.NumberUtil;
|
import io.github.dre2n.commons.util.NumberUtil;
|
||||||
import io.github.dre2n.dungeonsxl.DungeonsXL;
|
import io.github.dre2n.dungeonsxl.DungeonsXL;
|
||||||
|
import io.github.dre2n.dungeonsxl.config.MainConfig;
|
||||||
import io.github.dre2n.dungeonsxl.config.MainConfig.BackupMode;
|
import io.github.dre2n.dungeonsxl.config.MainConfig.BackupMode;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.WorldCreator;
|
||||||
|
import org.bukkit.WorldType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Daniel Saukel
|
* @author Daniel Saukel
|
||||||
@ -31,16 +35,21 @@ import org.bukkit.Bukkit;
|
|||||||
public class DWorlds {
|
public class DWorlds {
|
||||||
|
|
||||||
DungeonsXL plugin = DungeonsXL.getInstance();
|
DungeonsXL plugin = DungeonsXL.getInstance();
|
||||||
|
MainConfig mainConfig = plugin.getMainConfig();
|
||||||
|
|
||||||
|
public static final File RAW = new File(DungeonsXL.MAPS, ".raw");
|
||||||
|
|
||||||
private Set<DResourceWorld> resources = new HashSet<>();
|
private Set<DResourceWorld> resources = new HashSet<>();
|
||||||
private Set<DInstanceWorld> instances = new HashSet<>();
|
private Set<DInstanceWorld> instances = new HashSet<>();
|
||||||
|
|
||||||
public DWorlds(File folder) {
|
public DWorlds(File folder) {
|
||||||
for (File file : folder.listFiles()) {
|
for (File file : folder.listFiles()) {
|
||||||
if (file.isDirectory()) {
|
if (file.isDirectory() && !file.getName().equals(".raw")) {
|
||||||
resources.add(new DResourceWorld(this, file));
|
resources.add(new DResourceWorld(this, file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createRaw();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Getters and setters */
|
/* Getters and setters */
|
||||||
@ -203,11 +212,11 @@ public class DWorlds {
|
|||||||
* Clean up all instances.
|
* Clean up all instances.
|
||||||
*/
|
*/
|
||||||
public void deleteAllInstances() {
|
public void deleteAllInstances() {
|
||||||
BackupMode backupMode = plugin.getMainConfig().getBackupMode();
|
BackupMode backupMode = mainConfig.getBackupMode();
|
||||||
HashSet<DInstanceWorld> instances = new HashSet<>(this.instances);
|
HashSet<DInstanceWorld> instances = new HashSet<>(this.instances);
|
||||||
for (DInstanceWorld instance : instances) {
|
for (DInstanceWorld instance : instances) {
|
||||||
if (backupMode == BackupMode.ON_DISABLE | backupMode == BackupMode.ON_DISABLE_AND_SAVE && instance instanceof DEditWorld) {
|
if (backupMode == BackupMode.ON_DISABLE | backupMode == BackupMode.ON_DISABLE_AND_SAVE && instance instanceof DEditWorld) {
|
||||||
instance.getResource().backup(false);
|
instance.getResource().backup(mainConfig.areTweaksEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.delete();
|
instance.delete();
|
||||||
@ -246,4 +255,18 @@ public class DWorlds {
|
|||||||
return "DXL_" + (game ? "Game" : "Edit") + "_" + generateId();
|
return "DXL_" + (game ? "Game" : "Edit") + "_" + generateId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a raw, new flat world sothat it can be copied if needed instead of getting generated from scratch.
|
||||||
|
*/
|
||||||
|
public void createRaw() {
|
||||||
|
WorldCreator creator = WorldCreator.name(".raw");
|
||||||
|
creator.type(WorldType.FLAT);
|
||||||
|
creator.generateStructures(false);
|
||||||
|
World world = creator.createWorld();
|
||||||
|
File worldFolder = new File(Bukkit.getWorldContainer(), ".raw");
|
||||||
|
FileUtil.copyDirectory(worldFolder, RAW, DungeonsXL.EXCLUDED_FILES);
|
||||||
|
Bukkit.unloadWorld(world, false);
|
||||||
|
FileUtil.removeDirectory(worldFolder);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user