Removed uncaching as async saving can cause race condition

Fixed tests.
This commit is contained in:
tastybento 2020-04-19 14:02:45 -07:00
parent 6e64d274e8
commit c463170fdd
5 changed files with 96 additions and 75 deletions

View File

@ -16,6 +16,7 @@ import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.configuration.Config;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.Database;
@ -47,6 +48,13 @@ public class Level extends Addon {
private ConfigSettings settings;
private Config<ConfigSettings> configObject = new Config<>(this, ConfigSettings.class);
/**
* @param settings the settings to set
*/
public void setSettings(ConfigSettings settings) {
this.settings = settings;
}
// Database handler for level data
private Database<LevelsData> handler;
@ -89,6 +97,7 @@ public class Level extends Addon {
* @param targetPlayer - UUID of target player
* @return LevelsData object or null if not found
*/
@Nullable
public LevelsData getLevelsData(@NonNull UUID targetPlayer) {
// Get from database if not in cache
if (!levelsCache.containsKey(targetPlayer) && handler.objectExists(targetPlayer.toString())) {
@ -182,54 +191,19 @@ public class Level extends Addon {
// Start the top ten and register it for clicks
topTen = new TopTen(this);
registerListener(topTen);
// Register commands for AcidIsland and BSkyBlock
// Register commands for GameModes
getPlugin().getAddonsManager().getGameModeAddons().stream()
.filter(gm -> settings.getGameModes().contains(gm.getDescription().getName()))
.filter(gm -> settings
.getGameModes()
.contains(gm
.getDescription()
.getName()))
.forEach(gm -> {
log("Level hooking into " + gm.getDescription().getName());
gm.getAdminCommand().ifPresent(adminCommand -> {
new AdminLevelCommand(this, adminCommand);
new AdminTopCommand(this, adminCommand);
});
gm.getPlayerCommand().ifPresent(playerCmd -> {
new IslandLevelCommand(this, playerCmd);
new IslandTopCommand(this, playerCmd);
new IslandValueCommand(this, playerCmd);
});
registerCommands(gm);
// Register placeholders
if (getPlugin().getPlaceholdersManager() != null) {
// Island Level
getPlugin().getPlaceholdersManager().registerPlaceholder(this,
gm.getDescription().getName().toLowerCase() + "_island_level",
user -> getLevelPresenter().getLevelString(getIslandLevel(gm.getOverWorld(), user.getUniqueId())));
// Visited Island Level
getPlugin().getPlaceholdersManager().registerPlaceholder(this,
gm.getDescription().getName().toLowerCase() + "_visited_island_level",
user -> getPlugin().getIslands().getIslandAt(user.getLocation())
.map(island -> getIslandLevel(gm.getOverWorld(), island.getOwner()))
.map(level -> getLevelPresenter().getLevelString(level))
.orElse("0"));
// Top Ten
for (int i = 1; i <= 10; i++) {
final int rank = i;
// Value
getPlugin().getPlaceholdersManager().registerPlaceholder(this,
gm.getDescription().getName().toLowerCase() + "_top_value_" + rank,
user -> {
Collection<Long> values = getTopTen().getTopTenList(gm.getOverWorld()).getTopTen().values();
return values.size() < rank ? "" : values.stream().skip(rank - 1).findFirst().map(String::valueOf).orElse("");
});
// Name
getPlugin().getPlaceholdersManager().registerPlaceholder(this,
gm.getDescription().getName().toLowerCase() + "_top_name_" + rank,
user -> {
Collection<UUID> values = getTopTen().getTopTenList(gm.getOverWorld()).getTopTen().keySet();
return values.size() < rank ? "" : getPlayers().getName(values.stream().skip(rank - 1).findFirst().orElse(null));
});
}
registerPlaceholders(gm);
}
});
@ -242,15 +216,64 @@ public class Level extends Addon {
registerRequestHandler(new TopTenRequestHandler(this));
// Check if WildStackers is enabled on the server
if (Bukkit.getPluginManager().getPlugin("WildStacker") != null) {
// I only added support for counting blocks into the island level
// Someone else can PR if they want spawners added to the Leveling system :)
CalcIslandLevel.stackersEnabled = true;
} else CalcIslandLevel.stackersEnabled = false;
// I only added support for counting blocks into the island level
// Someone else can PR if they want spawners added to the Leveling system :)
CalcIslandLevel.stackersEnabled = Bukkit.getPluginManager().getPlugin("WildStacker") != null;
// Done
}
private void registerPlaceholders(GameModeAddon gm) {
// Island Level
getPlugin().getPlaceholdersManager().registerPlaceholder(this,
gm.getDescription().getName().toLowerCase() + "_island_level",
user -> getLevelPresenter().getLevelString(getIslandLevel(gm.getOverWorld(), user.getUniqueId())));
// Visited Island Level
getPlugin().getPlaceholdersManager().registerPlaceholder(this,
gm.getDescription().getName().toLowerCase() + "_visited_island_level", user -> getVisitedIslandLevel(gm, user));
// Top Ten
for (int i = 1; i <= 10; i++) {
final int rank = i;
// Value
getPlugin().getPlaceholdersManager().registerPlaceholder(this,
gm.getDescription().getName().toLowerCase() + "_top_value_" + rank,
user -> {
Collection<Long> values = getTopTen().getTopTenList(gm.getOverWorld()).getTopTen().values();
return values.size() < rank ? "" : values.stream().skip(rank - 1).findFirst().map(String::valueOf).orElse("");
});
// Name
getPlugin().getPlaceholdersManager().registerPlaceholder(this,
gm.getDescription().getName().toLowerCase() + "_top_name_" + rank,
user -> {
Collection<UUID> values = getTopTen().getTopTenList(gm.getOverWorld()).getTopTen().keySet();
return values.size() < rank ? "" : getPlayers().getName(values.stream().skip(rank - 1).findFirst().orElse(null));
});
}
}
private String getVisitedIslandLevel(GameModeAddon gm, User user) {
return getIslands().getIslandAt(user.getLocation())
.map(island -> getIslandLevel(gm.getOverWorld(), island.getOwner()))
.map(level -> getLevelPresenter().getLevelString(level))
.orElse("0");
}
private void registerCommands(GameModeAddon gm) {
gm.getAdminCommand().ifPresent(adminCommand -> {
new AdminLevelCommand(this, adminCommand);
new AdminTopCommand(this, adminCommand);
});
gm.getPlayerCommand().ifPresent(playerCmd -> {
new IslandLevelCommand(this, playerCmd);
new IslandTopCommand(this, playerCmd);
new IslandValueCommand(this, playerCmd);
});
}
/**
* Save the levels to the database
*/
@ -316,13 +339,6 @@ public class Level extends Addon {
return handler;
}
public void uncachePlayer(@Nullable UUID uniqueId) {
if (levelsCache.containsKey(uniqueId) && levelsCache.get(uniqueId) != null) {
handler.saveObject(levelsCache.get(uniqueId));
}
levelsCache.remove(uniqueId);
}
public static Addon getInstance() {
return addon;
}

View File

@ -4,12 +4,11 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import world.bentobox.level.Level;
/**
* Listens for when players join and leave
* Listens for when players join
* @author tastybento
*
*/
@ -36,10 +35,4 @@ public class JoinLeaveListener implements Listener {
}
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerQuit(PlayerQuitEvent e) {
addon.uncachePlayer(e.getPlayer().getUniqueId());
}
}

View File

@ -7,10 +7,7 @@ import world.bentobox.level.Level;
/**
* @author tastybento
*
* @deprecated As of 1.9.0, for removal.
*/
@Deprecated
public class LevelPlaceholder implements PlaceholderReplacer {
private final Level addon;

View File

@ -23,6 +23,7 @@ import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.level.calculators.PlayerLevel;
import world.bentobox.level.config.BlockConfig;
import world.bentobox.level.config.ConfigSettings;
/**
* @author tastybento
@ -39,7 +40,9 @@ public class LevelPresenterTest {
@Mock
private PlayerLevel pl;
@Mock
private BlockConfig settings;
private ConfigSettings settings;
@Mock
private BlockConfig blockConfig;
@Before
public void setUp() throws Exception {
@ -60,6 +63,7 @@ public class LevelPresenterTest {
// Settings
when(addon.getSettings()).thenReturn(settings);
when(addon.getBlockConfig()).thenReturn(blockConfig);
}
/**
@ -99,7 +103,7 @@ public class LevelPresenterTest {
*/
@Test
public void testGetLevelStringLongShorthand() {
when(settings.isShortHand()).thenReturn(true);
when(settings.isShorthand()).thenReturn(true);
LevelPresenter lp = new LevelPresenter(addon, plugin);
assertEquals("123.5M", lp.getLevelString(123456789L));
assertEquals("1.2k", lp.getLevelString(1234L));

View File

@ -65,6 +65,8 @@ import world.bentobox.bentobox.managers.FlagsManager;
import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.managers.PlaceholdersManager;
import world.bentobox.level.config.BlockConfig;
import world.bentobox.level.config.ConfigSettings;
import world.bentobox.level.listeners.IslandTeamListeners;
import world.bentobox.level.listeners.JoinLeaveListener;
@ -94,8 +96,6 @@ public class LevelTest {
private AddonsManager am;
@Mock
private BukkitScheduler scheduler;
@Mock
private Settings settings;
private Level addon;
@ -113,14 +113,23 @@ public class LevelTest {
@Mock
private PluginManager pim;
@Mock
private BlockConfig blockConfig;
@Mock
private Settings pluginSettings;
@BeforeClass
public static void beforeClass() throws IOException {
// Make the addon jar
jFile = new File("addon.jar");
// Copy over config file from src folder
Path fromPath = Paths.get("src/main/resources/config.yml");
Path path = Paths.get("config.yml");
Files.copy(fromPath, path);
// Copy over block config file from src folder
fromPath = Paths.get("src/main/resources/blockconfig.yml");
path = Paths.get("blockconfig.yml");
Files.copy(fromPath, path);
try (JarOutputStream tempJarOutputStream = new JarOutputStream(new FileOutputStream(jFile))) {
//Added the new files to the jar.
try (FileInputStream fis = new FileInputStream(path.toFile())) {
@ -185,6 +194,7 @@ public class LevelTest {
addon.setFile(jFile);
AddonDescription desc = new AddonDescription.Builder("bentobox", "Level", "1.3").description("test").authors("tastybento").build();
addon.setDescription(desc);
addon.setSettings(new ConfigSettings());
// Addons manager
when(plugin.getAddonsManager()).thenReturn(am);
// One game mode
@ -205,9 +215,9 @@ public class LevelTest {
when(fm.getFlags()).thenReturn(Collections.emptyList());
// The database type has to be created one line before the thenReturn() to work!
when(plugin.getSettings()).thenReturn(settings);
DatabaseType value = DatabaseType.JSON;
when(settings.getDatabaseType()).thenReturn(value);
when(plugin.getSettings()).thenReturn(pluginSettings);
when(pluginSettings.getDatabaseType()).thenReturn(value);
// Bukkit
PowerMockito.mockStatic(Bukkit.class);
@ -243,6 +253,7 @@ public class LevelTest {
public static void cleanUp() throws Exception {
new File("addon.jar").delete();
new File("config.yml").delete();
new File("blockconfig.yml").delete();
deleteAll(new File("addons"));
}
@ -261,7 +272,7 @@ public class LevelTest {
@Test
public void testOnEnable() {
addon.onEnable();
verify(plugin).logWarning("[Level] Level Addon: No such world in config.yml : acidisland_world");
verify(plugin).logWarning("[Level] Level Addon: No such world in blockconfig.yml : acidisland_world");
verify(plugin).log("[Level] Level hooking into BSkyBlock");
verify(cmd, times(3)).getAddon(); // Three commands
verify(adminCmd, times(2)).getAddon(); // Two commands
@ -311,8 +322,8 @@ public class LevelTest {
@Test
public void testGetSettings() {
addon.onEnable();
world.bentobox.level.config.BlockConfig s = addon.getSettings();
assertEquals(100, s.getDeathPenalty());
ConfigSettings s = addon.getSettings();
assertEquals(100, s.getLevelCost());
}
/**