Fix loading of global protections in custom worlds; resolves #513 and resolves #447

This commit is contained in:
Daniel Saukel 2019-01-09 19:26:38 +01:00
parent f92880ebd7
commit f7ca2c2dbd
8 changed files with 172 additions and 36 deletions

View File

@ -20,7 +20,6 @@ import java.util.ArrayList;
import java.util.List;
import org.bukkit.ChatColor;
import org.bukkit.inventory.Inventory;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitTask;
/**

View File

@ -17,22 +17,18 @@
package de.erethon.dungeonsxl.global;
import de.erethon.caliburn.category.Category;
import de.erethon.caliburn.item.VanillaItem;
import de.erethon.commons.chat.MessageUtil;
import de.erethon.commons.misc.NumberUtil;
import de.erethon.dungeonsxl.DungeonsXL;
import de.erethon.dungeonsxl.config.DMessage;
import de.erethon.dungeonsxl.game.Game;
import de.erethon.dungeonsxl.player.DGroup;
import de.erethon.dungeonsxl.util.LWCUtil;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Sign;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.material.Attachable;
/**
* Basically a GroupSign, but to form a game of multiple groups.
@ -121,6 +117,11 @@ public class GameSign extends JoinSign {
sign.update();
}
@Override
public String getDataPath() {
return "protections.gameSigns";
}
public void onPlayerInteract(Block block, Player player) {
DGroup dGroup = DGroup.getByPlayer(player);
if (dGroup == null) {

View File

@ -21,7 +21,6 @@ import de.erethon.commons.misc.NumberUtil;
import de.erethon.dungeonsxl.DungeonsXL;
import java.io.File;
import java.util.Map.Entry;
import java.util.Random;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
@ -54,30 +53,62 @@ public class GlobalData extends DREConfig {
@Override
public void load() {
for (World world : Bukkit.getWorlds()) {
ConfigurationSection gameSigns = config.getConfigurationSection("protections.gameSigns." + world.getName());
ConfigurationSection groupSigns = config.getConfigurationSection("protections.groupSigns." + world.getName());
ConfigurationSection leaveSigns = config.getConfigurationSection("protections.leaveSigns." + world.getName());
ConfigurationSection portals = config.getConfigurationSection("protections.portals." + world.getName());
Random random = new Random();
if (gameSigns != null) {
for (Entry<String, Object> entry : gameSigns.getValues(false).entrySet()) {
new GameSign(plugin, world, NumberUtil.parseInt(entry.getKey(), random.nextInt()), gameSigns.getConfigurationSection(entry.getKey()));
ConfigurationSection gameSigns = config.getConfigurationSection("protections.gameSigns");
ConfigurationSection groupSigns = config.getConfigurationSection("protections.groupSigns");
ConfigurationSection leaveSigns = config.getConfigurationSection("protections.leaveSigns");
ConfigurationSection portals = config.getConfigurationSection("protections.portals");
if (gameSigns != null) {
for (String worldName : gameSigns.getValues(false).keySet()) {
ConfigurationSection ws = gameSigns.getConfigurationSection(worldName);
for (Entry<String, Object> entry : ws.getValues(false).entrySet()) {
World world = Bukkit.getWorld(worldName);
if (world != null) {
new GameSign(plugin, world, NumberUtil.parseInt(entry.getKey()), ws.getConfigurationSection(entry.getKey()));
} else {
new UnloadedProtection<>(plugin, GameSign.class, worldName, NumberUtil.parseInt(entry.getKey()), ws.getConfigurationSection(entry.getKey()));
}
}
}
if (groupSigns != null) {
for (Entry<String, Object> entry : groupSigns.getValues(false).entrySet()) {
new GroupSign(plugin, world, NumberUtil.parseInt(entry.getKey(), random.nextInt()), groupSigns.getConfigurationSection(entry.getKey()));
}
if (groupSigns != null) {
for (String worldName : groupSigns.getValues(false).keySet()) {
ConfigurationSection ws = groupSigns.getConfigurationSection(worldName);
for (Entry<String, Object> entry : ws.getValues(false).entrySet()) {
World world = Bukkit.getWorld(worldName);
if (world != null) {
new GroupSign(plugin, world, NumberUtil.parseInt(entry.getKey()), ws.getConfigurationSection(entry.getKey()));
} else {
new UnloadedProtection<>(plugin, GroupSign.class, worldName, NumberUtil.parseInt(entry.getKey()), ws.getConfigurationSection(entry.getKey()));
}
}
}
if (leaveSigns != null) {
for (Entry<String, Object> entry : leaveSigns.getValues(false).entrySet()) {
new LeaveSign(plugin, world, NumberUtil.parseInt(entry.getKey(), random.nextInt()), leaveSigns.getConfigurationSection(entry.getKey()));
}
if (leaveSigns != null) {
for (String worldName : leaveSigns.getValues(false).keySet()) {
ConfigurationSection ws = leaveSigns.getConfigurationSection(worldName);
for (Entry<String, Object> entry : ws.getValues(false).entrySet()) {
World world = Bukkit.getWorld(worldName);
if (world != null) {
new LeaveSign(plugin, world, NumberUtil.parseInt(entry.getKey()), ws.getConfigurationSection(entry.getKey()));
} else {
new UnloadedProtection<>(plugin, LeaveSign.class, worldName, NumberUtil.parseInt(entry.getKey()), ws.getConfigurationSection(entry.getKey()));
}
}
}
if (portals != null) {
for (Entry<String, Object> entry : portals.getValues(false).entrySet()) {
new DPortal(plugin, world, NumberUtil.parseInt(entry.getKey(), random.nextInt()), portals.getConfigurationSection(entry.getKey()));
}
if (portals != null) {
for (String worldName : portals.getValues(false).keySet()) {
ConfigurationSection ws = portals.getConfigurationSection(worldName);
for (Entry<String, Object> entry : ws.getValues(false).entrySet()) {
World world = Bukkit.getWorld(worldName);
if (world != null) {
new DPortal(plugin, world, NumberUtil.parseInt(entry.getKey()), ws.getConfigurationSection(entry.getKey()));
} else {
new UnloadedProtection<>(plugin, DPortal.class, worldName, NumberUtil.parseInt(entry.getKey()), ws.getConfigurationSection(entry.getKey()));
}
}
}
}

View File

@ -19,7 +19,9 @@ package de.erethon.dungeonsxl.global;
import de.erethon.dungeonsxl.DungeonsXL;
import de.erethon.dungeonsxl.player.DGroup;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.bukkit.Location;
import org.bukkit.World;
@ -35,6 +37,7 @@ public class GlobalProtectionCache {
private DungeonsXL plugin;
private Set<GlobalProtection> protections = new HashSet<>();
private Map<UnloadedProtection, String> unloaded = new HashMap<>();
public GlobalProtectionCache(DungeonsXL plugin) {
this.plugin = plugin;
@ -69,6 +72,13 @@ public class GlobalProtectionCache {
return protections;
}
/**
* @return the protections that are known but not loaded yet
*/
public Map<UnloadedProtection, String> getUnloadedProtections() {
return unloaded;
}
/**
* @param type All protections which are an instance of it will be returned.
* @return the protections of the type
@ -131,8 +141,8 @@ public class GlobalProtectionCache {
public int generateId(Class<? extends GlobalProtection> type, World world) {
int id = 1;
for (GlobalProtection protection : protections) {
if (protection.getClass() == type) {
id++;
if (protection.getClass() == type && id <= protection.getId()) {
id = protection.getId() + 1;
}
}
return id;

View File

@ -23,7 +23,10 @@ import de.erethon.dungeonsxl.config.DMessage;
import de.erethon.dungeonsxl.player.DGlobalPlayer;
import de.erethon.dungeonsxl.player.DPermission;
import de.erethon.dungeonsxl.world.DEditWorld;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
@ -42,6 +45,7 @@ import org.bukkit.event.player.PlayerBucketFillEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerPortalEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.inventory.ItemStack;
/**
@ -281,4 +285,14 @@ public class GlobalProtectionListener implements Listener {
}
}
@EventHandler
public void onWorldLoad(WorldLoadEvent event) {
World world = event.getWorld();
for (Entry<UnloadedProtection, String> entry : new HashSet<>(plugin.getGlobalProtectionCache().getUnloadedProtections().entrySet())) {
if (world.getName().equals(entry.getValue())) {
entry.getKey().load(world);
}
}
}
}

View File

@ -17,25 +17,18 @@
package de.erethon.dungeonsxl.global;
import de.erethon.caliburn.category.Category;
import de.erethon.caliburn.item.VanillaItem;
import de.erethon.commons.chat.MessageUtil;
import de.erethon.commons.compatibility.Version;
import de.erethon.commons.misc.NumberUtil;
import de.erethon.dungeonsxl.DungeonsXL;
import de.erethon.dungeonsxl.config.DMessage;
import de.erethon.dungeonsxl.player.DGroup;
import de.erethon.dungeonsxl.util.LWCUtil;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.Sign;
import org.bukkit.block.data.Directional;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.material.Attachable;
/**
* A sign to form a group and to define its dungeon.
@ -127,10 +120,15 @@ public class GroupSign extends JoinSign {
sign.update();
}
@Override
public String getDataPath() {
return "protections.groupSigns";
}
@Override
public void save(FileConfiguration config) {
super.save(config);
String preString = "protections.groupSigns." + getWorld().getName() + "." + getId();
String preString = getDataPath() + "." + getWorld().getName() + "." + getId();
config.set(preString + ".groupName", groupName);
}

View File

@ -36,7 +36,7 @@ import org.bukkit.material.Attachable;
/**
* @author Daniel Saukel
*/
public class JoinSign extends GlobalProtection {
public abstract class JoinSign extends GlobalProtection {
protected Dungeon dungeon;
protected int maxElements;
@ -195,9 +195,14 @@ public class JoinSign extends GlobalProtection {
}
}
/**
* @return the path in the global data file
*/
public abstract String getDataPath();
@Override
public void save(FileConfiguration config) {
String preString = "protections.groupSigns." + getWorld().getName() + "." + getId();
String preString = getDataPath() + "." + getWorld().getName() + "." + getId();
config.set(preString + ".x", startSign.getX());
config.set(preString + ".y", startSign.getY());

View File

@ -0,0 +1,78 @@
/*
* Copyright (C) 2012-2019 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 de.erethon.dungeonsxl.global;
import de.erethon.commons.chat.MessageUtil;
import de.erethon.dungeonsxl.DungeonsXL;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
/**
* @author Daniel Saukel
*/
public class UnloadedProtection<T extends GlobalProtection> {
private DungeonsXL plugin;
private GlobalProtectionCache cache;
private Constructor constructor;
private String worldName;
private int id;
private ConfigurationSection config;
public UnloadedProtection(DungeonsXL plugin, Class<T> type, String worldName, int id, ConfigurationSection config) {
this.plugin = plugin;
try {
constructor = type.getConstructor(DungeonsXL.class, World.class, int.class, ConfigurationSection.class);
} catch (NoSuchMethodException | SecurityException exception) {
// Don't register
return;
}
this.worldName = worldName;
this.id = id;
this.config = config;
cache = plugin.getGlobalProtectionCache();
cache.getUnloadedProtections().put(this, worldName);
}
public T load(World world) {
if (!world.getName().equals(worldName)) {
throw new IllegalArgumentException("World mismatch: Expected " + worldName + ", but received " + world);
}
T protection = null;
try {
protection = (T) constructor.newInstance(plugin, world, id, config);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException exception) {
MessageUtil.log(plugin, "Could not find or invoke " + constructor);
exception.printStackTrace();
}
if (protection != null) {
cache.getUnloadedProtections().remove(this);
}
return protection;
}
@Override
public String toString() {
return "UnloadedProtection{type=" + constructor.getDeclaringClass().getName() + "; " + "world=" + worldName + "}";
}
}