mirror of
https://github.com/Artillex-Studios/AxMinions.git
synced 2024-11-29 12:45:18 +01:00
Performance, fixes
This commit is contained in:
parent
c8a6d01b0b
commit
2539ab790e
@ -42,7 +42,6 @@ public final class Skins {
|
||||
Skin skin = Skin.of(route, mapList);
|
||||
SkinRegistry.register(skin);
|
||||
}
|
||||
// TODO: Refresh minion skins
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -136,12 +136,29 @@ public final class DataHandler {
|
||||
.select()
|
||||
.from(Tables.USERS)
|
||||
.where(Fields.UUID.eq(player.getUniqueId()))
|
||||
.limit(1)
|
||||
.fetch();
|
||||
|
||||
if (!select.isEmpty()) {
|
||||
Record record = select.get(0);
|
||||
LogUtils.debug("User data select record: {}", record);
|
||||
return new User(record.get(Fields.ID), player.getUniqueId(), player.getName(), texture, record.get(Fields.EXTRA_SLOTS, int.class), record.get(Fields.ISLAND_SLOTS, int.class));
|
||||
int ownerId = record.get(Fields.ID);
|
||||
|
||||
Result<Record1<Integer>> minionSelect = DatabaseConnector.getInstance().context()
|
||||
.selectCount()
|
||||
.from(Tables.MINIONS)
|
||||
.where(Fields.OWNER_ID.eq(ownerId))
|
||||
.limit(1)
|
||||
.fetch();
|
||||
|
||||
if (!minionSelect.isEmpty()) {
|
||||
Record minionRecord = minionSelect.get(0);
|
||||
int minionCount = minionRecord.get(0, int.class);
|
||||
|
||||
return new User(ownerId, player.getUniqueId(), player.getName(), texture, minionCount, record.get(Fields.EXTRA_SLOTS, int.class), record.get(Fields.ISLAND_SLOTS, int.class), new ArrayList<>());
|
||||
}
|
||||
|
||||
return new User(ownerId, player.getUniqueId(), player.getName(), texture, 0, record.get(Fields.EXTRA_SLOTS, int.class), record.get(Fields.ISLAND_SLOTS, int.class), new ArrayList<>());
|
||||
}
|
||||
|
||||
Record1<Integer> insert = DatabaseConnector.getInstance().context()
|
||||
@ -157,12 +174,11 @@ public final class DataHandler {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new User(insert.get(Fields.ID), player.getUniqueId(), player.getName(), texture, 0, 0);
|
||||
return new User(insert.get(Fields.ID), player.getUniqueId(), player.getName(), texture, 0, 0, 0, new ArrayList<>());
|
||||
}, AsyncUtils.executor()).exceptionallyAsync(throwable -> {
|
||||
log.error("An unexpected error occurred while updating user {}!", player.getName(), throwable);
|
||||
return null;
|
||||
}, AsyncUtils.executor());
|
||||
|
||||
}
|
||||
|
||||
public static int worldId(World world) {
|
||||
@ -170,6 +186,7 @@ public final class DataHandler {
|
||||
.select()
|
||||
.from(Tables.WORLDS)
|
||||
.where(Fields.WORLD_UUID.eq(world.getUID()))
|
||||
.limit(1)
|
||||
.fetch();
|
||||
|
||||
if (!select.isEmpty()) {
|
||||
@ -199,6 +216,7 @@ public final class DataHandler {
|
||||
.and(Fields.LOCATION_X.eq(location.getBlockX()))
|
||||
.and(Fields.LOCATION_Y.eq(location.getBlockY()))
|
||||
.and(Fields.LOCATION_Z.eq(location.getBlockZ())))
|
||||
.limit(1)
|
||||
.fetch();
|
||||
|
||||
if (!select.isEmpty()) {
|
||||
@ -228,6 +246,7 @@ public final class DataHandler {
|
||||
.select()
|
||||
.from(Tables.TYPES)
|
||||
.where(Fields.ID.eq((int) id))
|
||||
.limit(1)
|
||||
.fetchSingle(Fields.NAME);
|
||||
}
|
||||
|
||||
@ -277,6 +296,7 @@ public final class DataHandler {
|
||||
return IntLongPair.of(0, 0);
|
||||
}
|
||||
|
||||
List<Minion> toLoad = new ArrayList<>();
|
||||
Result<Record> locations = DatabaseConnector.getInstance().context()
|
||||
.select()
|
||||
.from(Tables.LOCATIONS)
|
||||
@ -289,6 +309,7 @@ public final class DataHandler {
|
||||
.select()
|
||||
.from(Tables.MINIONS)
|
||||
.where(Fields.LOCATION_ID.eq(id))
|
||||
.limit(1)
|
||||
.fetch();
|
||||
|
||||
if (minions.isEmpty()) {
|
||||
@ -321,10 +342,12 @@ public final class DataHandler {
|
||||
|
||||
MinionData data = new MinionData(ownerId, type, Direction.entries[facing], null, minionLevel, charge, tool == null ? new ItemStack(Material.AIR) : WrappedItemStack.wrap(tool).toBukkit(), null, MinionData.deserialize(extraData));
|
||||
Minion minion = new Minion(new Location(world, x + 0.5, y, z + 0.5), data);
|
||||
MinionWorldCache.add(minion);
|
||||
toLoad.add(minion);
|
||||
minion.spawn();
|
||||
loadedMinions++;
|
||||
}
|
||||
|
||||
MinionWorldCache.addAll(toLoad);
|
||||
long took = System.nanoTime() - start;
|
||||
return IntLongPair.of(loadedMinions, took);
|
||||
}, AsyncUtils.executor()).exceptionallyAsync(throwable -> {
|
||||
@ -340,6 +363,7 @@ public final class DataHandler {
|
||||
.select()
|
||||
.from(Tables.TYPES)
|
||||
.where(Fields.NAME.eq(type.name()))
|
||||
.limit(1)
|
||||
.fetch();
|
||||
|
||||
if (!select.isEmpty()) {
|
||||
@ -395,7 +419,7 @@ public final class DataHandler {
|
||||
.set(Fields.LEVEL, minion.level())
|
||||
.set(Fields.CHARGE, minion.charge())
|
||||
.set(Fields.FACING, minion.facing().ordinal())
|
||||
.set(Fields.TOOL, WrappedItemStack.wrap(minion.tool()).serialize())
|
||||
.set(Fields.TOOL, minion.tool().getType().isAir() ? new byte[0] : WrappedItemStack.wrap(minion.tool()).serialize())
|
||||
.set(Fields.EXTRA_DATA, MinionData.serialize(minion.extraData()))
|
||||
.where(Fields.LOCATION_ID.eq(locationId));
|
||||
|
||||
|
@ -82,7 +82,6 @@ public final class MinionPlaceListener implements Listener {
|
||||
}
|
||||
|
||||
// TODO: level
|
||||
itemStack.setAmount(itemStack.getAmount() - 1);
|
||||
Location location = LocationUtils.toBlockCenter(clickedBlock.getRelative(event.getBlockFace()).getLocation());
|
||||
|
||||
MinionArea area = MinionWorldCache.getArea(location.getWorld());
|
||||
@ -97,15 +96,19 @@ public final class MinionPlaceListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
itemStack.setAmount(itemStack.getAmount() - 1);
|
||||
LogUtils.debug("Minion count for user: " + user.minionCount());
|
||||
// TODO: Database queries, etc..
|
||||
MinionData data = new MinionData(user.id(), minionType, Direction.NORTH, null, minionType.level(1), 0, null, null, new HashMap<>());
|
||||
data.extraData().put("owner_texture", NMSHandlers.getNmsHandler().textures(event.getPlayer()).getKey());
|
||||
Minion minion = new Minion(location, data);
|
||||
MinionWorldCache.add(minion);
|
||||
user.minionCount(user.minionCount() + 1);
|
||||
|
||||
DataHandler.insertMinion(minion).thenRun(() -> {
|
||||
LogUtils.debug("Inserted minion!");
|
||||
});
|
||||
minion.spawn();
|
||||
area.startTicking(location.getChunk());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
package com.artillexstudios.axminions.listeners;
|
||||
|
||||
import com.artillexstudios.axminions.database.DataHandler;
|
||||
import com.artillexstudios.axminions.users.User;
|
||||
import com.artillexstudios.axminions.minions.Minion;
|
||||
import com.artillexstudios.axminions.minions.MinionWorldCache;
|
||||
import com.artillexstudios.axminions.users.Users;
|
||||
import com.artillexstudios.axminions.utils.LogUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
@ -14,9 +15,22 @@ public final class PlayerListener implements Listener {
|
||||
@EventHandler
|
||||
public void onPlayerJoinEvent(PlayerJoinEvent event) {
|
||||
DataHandler.loadUser(event.getPlayer()).thenAccept(user -> {
|
||||
LogUtils.debug("Loaded user");
|
||||
if (user == null) {
|
||||
LogUtils.warn("Failed to load user data for player {}!", event.getPlayer().getName());
|
||||
return;
|
||||
}
|
||||
|
||||
LogUtils.debug("Loaded user for player: {}", event.getPlayer().getName());
|
||||
Users.load(user);
|
||||
// TODO: Update all minions placed by the user
|
||||
|
||||
ObjectArrayList<Minion> copy = MinionWorldCache.copy();
|
||||
for (Minion minion : copy) {
|
||||
if (minion.ownerId() == user.id()) {
|
||||
user.minions().add(minion);
|
||||
minion.extraData().put("owner_texture", user.texture());
|
||||
minion.skin(minion.skin());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,12 @@
|
||||
package com.artillexstudios.axminions.listeners;
|
||||
|
||||
import com.artillexstudios.axapi.scheduler.Scheduler;
|
||||
import com.artillexstudios.axminions.database.DataHandler;
|
||||
import com.artillexstudios.axminions.minions.MinionArea;
|
||||
import com.artillexstudios.axminions.minions.MinionWorldCache;
|
||||
import com.artillexstudios.axminions.utils.LogUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.WorldLoadEvent;
|
||||
@ -10,7 +16,24 @@ public final class WorldListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onWorldLoadEvent(WorldLoadEvent event) {
|
||||
MinionWorldCache.loadArea(event.getWorld());
|
||||
MinionArea area = MinionWorldCache.loadArea(event.getWorld());
|
||||
DataHandler.loadMinions(event.getWorld()).toCompletableFuture().thenAccept(loaded -> {
|
||||
LogUtils.debug("Loaded {} minions in world {} in {} ms!", loaded.firstInt(), event.getWorld().getName(), loaded.secondLong() / 1_000_000);
|
||||
|
||||
if (area == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Scheduler.get().run(() -> {
|
||||
if (Bukkit.getWorld(event.getWorld().getUID()) == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Chunk chunk : event.getWorld().getLoadedChunks()) {
|
||||
area.startTicking(chunk);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
@ -149,6 +149,7 @@ public final class Minion {
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
this.ticking = false;
|
||||
this.entity.remove();
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,11 @@ public final class MinionSaver {
|
||||
if (this.future != null && !this.future.isCancelled()) {
|
||||
this.future.cancel(false);
|
||||
this.future = null;
|
||||
|
||||
ObjectArrayList<Minion> copy = MinionWorldCache.copy();
|
||||
DataHandler.saveMinions(copy).toCompletableFuture().thenAccept(pair -> {
|
||||
LogUtils.debug("Saved {} minions in {} ms!", pair.firstLong(), pair.secondLong() / 1_000_000L);
|
||||
}).join();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,18 +6,21 @@ import org.bukkit.World;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
|
||||
public final class MinionWorldCache {
|
||||
private static final IdentityHashMap<World, MinionArea> worlds = new IdentityHashMap<>();
|
||||
private static final ObjectArrayList<Minion> minions = new ObjectArrayList<>();
|
||||
|
||||
public static void loadArea(World world) {
|
||||
public static MinionArea loadArea(World world) {
|
||||
if (worlds.containsKey(world)) {
|
||||
LogUtils.warn("An area is already present for world {}", world.getName());
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
worlds.put(world, new MinionArea());
|
||||
MinionArea area = new MinionArea();
|
||||
worlds.put(world, area);
|
||||
return area;
|
||||
}
|
||||
|
||||
public static void add(Minion minion) {
|
||||
@ -31,6 +34,17 @@ public final class MinionWorldCache {
|
||||
area.load(minion);
|
||||
}
|
||||
|
||||
public static void addAll(List<Minion> list) {
|
||||
minions.addAll(list);
|
||||
MinionArea area = worlds.get(list.get(0).location().getWorld());
|
||||
if (area == null) {
|
||||
LogUtils.error("Tried to add minions to unknown world! {}", list);
|
||||
return;
|
||||
}
|
||||
|
||||
area.loadAll(list);
|
||||
}
|
||||
|
||||
public static void remove(Minion minion) {
|
||||
minions.remove(minion);
|
||||
MinionArea area = worlds.get(minion.location().getWorld());
|
||||
@ -60,6 +74,7 @@ public final class MinionWorldCache {
|
||||
|
||||
area.forEachPos(position -> {
|
||||
for (Minion minion : position.minions()) {
|
||||
minions.remove(minion);
|
||||
minion.destroy();
|
||||
}
|
||||
});
|
||||
|
@ -4,6 +4,7 @@ import com.artillexstudios.axminions.exception.MinionTickFailException;
|
||||
import com.artillexstudios.axminions.minions.actions.filters.Filter;
|
||||
import com.artillexstudios.axminions.utils.LogUtils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
@ -18,6 +19,7 @@ public enum CollectorShape {
|
||||
final int blockX = location.getBlockX();
|
||||
final int blockY = location.getBlockY();
|
||||
final int blockZ = location.getBlockZ();
|
||||
final World world = location.getWorld();
|
||||
|
||||
final double rangeSquared = range * range;
|
||||
final double smallRangeSquared = ((range - 1) * (range - 1));
|
||||
@ -39,7 +41,7 @@ public enum CollectorShape {
|
||||
|
||||
if (distance < rangeSquared && distance < smallRangeSquared) {
|
||||
try {
|
||||
Location newLocation = new Location(location.getWorld(), x, y, z);
|
||||
Location newLocation = new Location(world, x, y, z);
|
||||
for (Filter<?> filter : filters) {
|
||||
if (!filter.isAllowed(newLocation)) {
|
||||
continue z;
|
||||
@ -70,6 +72,7 @@ public enum CollectorShape {
|
||||
final int blockX = location.getBlockX();
|
||||
final int blockY = location.getBlockY();
|
||||
final int blockZ = location.getBlockZ();
|
||||
final World world = location.getWorld();
|
||||
|
||||
final double rangeSquared = range * range;
|
||||
final double smallRangeSquared = ((range - 1) * (range - 1));
|
||||
@ -87,7 +90,7 @@ public enum CollectorShape {
|
||||
|
||||
if (distance < rangeSquared && distance < smallRangeSquared) {
|
||||
try {
|
||||
Location newLocation = new Location(location.getWorld(), x, blockY, z);
|
||||
Location newLocation = new Location(world, x, blockY, z);
|
||||
for (Filter<?> filter : filters) {
|
||||
if (!filter.isAllowed(newLocation)) {
|
||||
continue z;
|
||||
@ -117,6 +120,7 @@ public enum CollectorShape {
|
||||
final int blockX = location.getBlockX();
|
||||
final int blockY = location.getBlockY();
|
||||
final int blockZ = location.getBlockZ();
|
||||
final World world = location.getWorld();
|
||||
|
||||
final int xStart = (int) Math.round(blockX - range);
|
||||
final int xEnd = (int) Math.round(blockX + range);
|
||||
@ -127,7 +131,7 @@ public enum CollectorShape {
|
||||
z:
|
||||
for (int z = zStart; z <= zEnd; z++) {
|
||||
try {
|
||||
Location newLocation = new Location(location.getWorld(), x, blockY, z);
|
||||
Location newLocation = new Location(world, x, blockY, z);
|
||||
for (Filter<?> filter : filters) {
|
||||
if (!filter.isAllowed(newLocation)) {
|
||||
continue z;
|
||||
@ -156,6 +160,7 @@ public enum CollectorShape {
|
||||
final int blockX = location.getBlockX();
|
||||
final int blockY = location.getBlockY();
|
||||
final int blockZ = location.getBlockZ();
|
||||
final World world = location.getWorld();
|
||||
|
||||
final int xStart = (int) Math.round(blockX - range);
|
||||
final int xEnd = (int) Math.round(blockX + range);
|
||||
@ -169,7 +174,7 @@ public enum CollectorShape {
|
||||
z:
|
||||
for (int z = zStart; z <= zEnd; z++) {
|
||||
try {
|
||||
Location newLocation = new Location(location.getWorld(), x, y, z);
|
||||
Location newLocation = new Location(world, x, y, z);
|
||||
for (Filter<?> filter : filters) {
|
||||
if (!filter.isAllowed(newLocation)) {
|
||||
continue z;
|
||||
|
@ -1,14 +1,14 @@
|
||||
package com.artillexstudios.axminions.minions.actions.filters;
|
||||
|
||||
import com.artillexstudios.axminions.exception.TransformerNotPresentException;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class Filter<T> {
|
||||
private final IdentityHashMap<Class<?>, Transformer<?, ?>> transformers = new IdentityHashMap<>();
|
||||
private final Object2ObjectArrayMap<Class<?>, Transformer<?, ?>> transformers = new Object2ObjectArrayMap<>();
|
||||
private final Collection<Transformer<?, ?>> unmodifiableTransformers = Collections.unmodifiableCollection(transformers.values());
|
||||
|
||||
public abstract boolean isAllowed(Object object);
|
||||
|
@ -9,14 +9,16 @@ import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class MaterialFilter extends Filter<Material> {
|
||||
private final HashSet<Material> allowed = new HashSet<>();
|
||||
private final Set<Material> allowed = Collections.newSetFromMap(new EnumMap<>(Material.class));
|
||||
|
||||
public MaterialFilter(Map<Object, Object> configuration) {
|
||||
this.addTransformer(Location.class, new Transformer<Location, Material>() {
|
||||
|
@ -1,6 +1,13 @@
|
||||
package com.artillexstudios.axminions.users;
|
||||
|
||||
import com.artillexstudios.axminions.minions.Minion;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public record User(int id, UUID uuid, String name, String texture, int extraSlots, int extraIslandSlots) {
|
||||
public record User(int id, UUID uuid, String name, String texture, int minionCount, int extraSlots, int extraIslandSlots, List<Minion> minions) {
|
||||
|
||||
public void minionCount(int minionCount) {
|
||||
Users.load(new User(this.id, this.uuid, this.name, this.texture, minionCount, this.extraSlots, this.extraIslandSlots, this.minions));
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import org.bukkit.entity.Player;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class Users {
|
||||
public final class Users {
|
||||
private static final ConcurrentHashMap<UUID, User> USER_CACHE = new ConcurrentHashMap<>(100);
|
||||
|
||||
public static void load(User user) {
|
||||
|
@ -20,6 +20,8 @@ public record ChunkPos(int x, int z, AtomicBoolean ticking, ObjectArrayList<Mini
|
||||
}
|
||||
|
||||
public void addMinion(Minion minion) {
|
||||
minion.ticking(this.ticking.get());
|
||||
|
||||
this.minions.add(minion);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user