1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-19 19:25:48 +00:00

Added AsyncProfileLoadEvent

This commit is contained in:
TheBusyBiscuit 2021-01-23 19:38:59 +01:00
parent f2a80fc04f
commit 17fd2ec570
5 changed files with 198 additions and 10 deletions

View File

@ -29,6 +29,7 @@
#### Additions
* Added a new language: Bulgarian
* Added a new language: Hebrew
* (API) Added AsyncProfileLoadEvent
#### Changes
* Massive performance improvements to holograms/armorstands

View File

@ -0,0 +1,75 @@
package io.github.thebusybiscuit.slimefun4.api.events;
import java.util.UUID;
import javax.annotation.Nonnull;
import org.apache.commons.lang.Validate;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
/**
* This {@link Event} is called when the {@link PlayerProfile} of a {@link Player}
* is loaded into memory.
* The {@link AsyncProfileLoadEvent} is called asynchronously and can be used to "inject"
* a custom {@link PlayerProfile} if necessary.
*
* @author TheBusyBiscuit
*
* @see PlayerProfile
*
*/
public class AsyncProfileLoadEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private final UUID uniqueId;
private PlayerProfile profile;
public AsyncProfileLoadEvent(@Nonnull PlayerProfile profile) {
super(true);
Validate.notNull(profile, "The Profile cannot be null");
this.uniqueId = profile.getUUID();
this.profile = profile;
}
@Nonnull
public UUID getPlayerUUID() {
return uniqueId;
}
@Nonnull
public PlayerProfile getProfile() {
return profile;
}
/**
* This method can be used to inject your custom {@link PlayerProfile} implementations.
* However, the passed {@link PlayerProfile} must have the same {@link UUID} as the original one!
*
* @param profile
* The {@link PlayerProfile}
*/
public void setProfile(@Nonnull PlayerProfile profile) {
Validate.notNull(profile, "The PlayerProfile cannot be null!");
Validate.isTrue(profile.getUUID().equals(uniqueId), "Cannot inject a PlayerProfile with a different UUID");
this.profile = profile;
}
@Nonnull
public static HandlerList getHandlerList() {
return handlers;
}
@Nonnull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
}

View File

@ -1,6 +1,5 @@
package io.github.thebusybiscuit.slimefun4.api.player;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@ -33,6 +32,7 @@ import com.google.common.collect.ImmutableSet;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.config.Config;
import io.github.thebusybiscuit.slimefun4.api.events.AsyncProfileLoadEvent;
import io.github.thebusybiscuit.slimefun4.api.gps.Waypoint;
import io.github.thebusybiscuit.slimefun4.api.items.HashedArmorpiece;
import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectionType;
@ -56,7 +56,7 @@ import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
* @see HashedArmorpiece
*
*/
public final class PlayerProfile {
public class PlayerProfile {
private final UUID uuid;
private final String name;
@ -74,13 +74,17 @@ public final class PlayerProfile {
private final HashedArmorpiece[] armor = { new HashedArmorpiece(), new HashedArmorpiece(), new HashedArmorpiece(), new HashedArmorpiece() };
private PlayerProfile(@Nonnull OfflinePlayer p) {
protected PlayerProfile(@Nonnull OfflinePlayer p) {
this.uuid = p.getUniqueId();
this.name = p.getName();
configFile = new Config(new File("data-storage/Slimefun/Players/" + uuid.toString() + ".yml"));
configFile = new Config("data-storage/Slimefun/Players/" + uuid.toString() + ".yml");
waypointsFile = new Config("data-storage/Slimefun/waypoints/" + uuid.toString() + ".yml");
loadProfileData();
}
private void loadProfileData() {
for (Research research : SlimefunPlugin.getRegistry().getResearches()) {
if (configFile.contains("researches." + research.getID())) {
researches.add(research);
@ -95,7 +99,7 @@ public final class PlayerProfile {
waypoints.add(new Waypoint(this, key, loc, waypointName));
}
} catch (Exception x) {
SlimefunPlugin.logger().log(Level.WARNING, x, () -> "Could not load Waypoint \"" + key + "\" for Player \"" + p.getName() + '"');
SlimefunPlugin.logger().log(Level.WARNING, x, () -> "Could not load Waypoint \"" + key + "\" for Player \"" + name + '"');
}
}
}
@ -268,14 +272,14 @@ public final class PlayerProfile {
* Call this method if the Player has left.
* The profile can then be removed from RAM.
*/
public void markForDeletion() {
public final void markForDeletion() {
markedForDeletion = true;
}
/**
* Call this method if this Profile has unsaved changes.
*/
public void markDirty() {
public final void markDirty() {
dirty = true;
}
@ -382,9 +386,11 @@ public final class PlayerProfile {
}
Bukkit.getScheduler().runTaskAsynchronously(SlimefunPlugin.instance(), () -> {
PlayerProfile pp = new PlayerProfile(p);
SlimefunPlugin.getRegistry().getPlayerProfiles().put(uuid, pp);
callback.accept(pp);
AsyncProfileLoadEvent event = new AsyncProfileLoadEvent(new PlayerProfile(p));
Bukkit.getPluginManager().callEvent(event);
SlimefunPlugin.getRegistry().getPlayerProfiles().put(uuid, event.getProfile());
callback.accept(event.getProfile());
});
return false;

View File

@ -0,0 +1,13 @@
package io.github.thebusybiscuit.slimefun4.testing.tests.profiles;
import org.bukkit.OfflinePlayer;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
class MockProfile extends PlayerProfile {
MockProfile(OfflinePlayer p) {
super(p);
}
}

View File

@ -0,0 +1,93 @@
package io.github.thebusybiscuit.slimefun4.testing.tests.profiles;
import org.bukkit.OfflinePlayer;
import org.bukkit.event.Event;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.ServerMock;
import be.seeseemelk.mockbukkit.entity.OfflinePlayerMock;
import io.github.thebusybiscuit.slimefun4.api.events.AsyncProfileLoadEvent;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
class TestAsyncProfileLoadEvent {
private static ServerMock server;
@BeforeAll
public static void load() {
server = MockBukkit.mock();
MockBukkit.load(SlimefunPlugin.class);
}
@AfterAll
public static void unload() {
MockBukkit.unmock();
}
@Test
@DisplayName("Test AsyncProfileLoadEvent being thrown")
void testEventFired() throws InterruptedException {
server.getPluginManager().clearEvents();
OfflinePlayer player = new OfflinePlayerMock("EventFire");
TestUtilities.awaitProfile(player);
server.getPluginManager().assertEventFired(AsyncProfileLoadEvent.class, Event::isAsynchronous);
}
@Test
@DisplayName("Test AsyncProfileLoadEvent#getProfile()")
void testEventGetter() throws InterruptedException {
server.getPluginManager().clearEvents();
OfflinePlayer player = new OfflinePlayerMock("GetProfile");
PlayerProfile profile = TestUtilities.awaitProfile(player);
server.getPluginManager().assertEventFired(AsyncProfileLoadEvent.class, e -> e.getProfile().equals(profile));
}
@Test
@DisplayName("Test Profile Injection")
void testProfileInjection() throws InterruptedException {
OfflinePlayer player = new OfflinePlayerMock("SomePlayer");
PlayerProfile profile = TestUtilities.awaitProfile(player);
PlayerProfile mockProfile = new MockProfile(player);
AsyncProfileLoadEvent event = new AsyncProfileLoadEvent(profile);
Assertions.assertEquals(player.getUniqueId(), event.getPlayerUUID());
Assertions.assertEquals(profile, event.getProfile());
Assertions.assertFalse(event.getProfile() instanceof MockProfile);
event.setProfile(mockProfile);
Assertions.assertEquals(mockProfile, event.getProfile());
Assertions.assertTrue(event.getProfile() instanceof MockProfile);
}
@Test
@DisplayName("Test Profile Mismatch")
void testProfileMismatch() throws InterruptedException {
OfflinePlayer player = new OfflinePlayerMock("ValidProfile");
OfflinePlayer player2 = new OfflinePlayerMock("UnrelatedProfile");
PlayerProfile profile = TestUtilities.awaitProfile(player);
PlayerProfile profile2 = TestUtilities.awaitProfile(player2);
AsyncProfileLoadEvent event = new AsyncProfileLoadEvent(profile);
// Profile is null
Assertions.assertThrows(IllegalArgumentException.class, () -> event.setProfile(null));
// UUID mismatch
Assertions.assertThrows(IllegalArgumentException.class, () -> event.setProfile(profile2));
}
}