Skip to content

Commit

Permalink
Optimization SkylliaOre
Browse files Browse the repository at this point in the history
  • Loading branch information
Euphillya committed Jan 3, 2025
1 parent 178c5ee commit cf84d9a
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 68 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package fr.euphyllia.skylliabank.commands;

import fr.euphyllia.skyllia.api.PermissionImp;
import fr.euphyllia.skyllia.api.SkylliaAPI;
import fr.euphyllia.skyllia.api.commands.SubCommandInterface;
import fr.euphyllia.skyllia.api.skyblock.Island;
Expand Down Expand Up @@ -481,7 +482,7 @@ private void handleSetBalance(CommandSender sender, String[] args) {
@Override
public boolean onCommand(@NotNull Plugin plugin, @NotNull CommandSender sender, @NotNull String[] args) {
// noPermission
if (!sender.hasPermission("skyllia.bank.admin")) {
if (!PermissionImp.hasPermission(sender, "skyllia.bank.admin")) {
LanguageToml.sendMessage(
sender,
SkylliaBank.getConfiguration().getString(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package fr.euphyllia.skylliabank.commands;

import fr.euphyllia.skyllia.api.PermissionImp;
import fr.euphyllia.skyllia.api.SkylliaAPI;
import fr.euphyllia.skyllia.api.commands.SubCommandInterface;
import fr.euphyllia.skyllia.api.skyblock.Island;
Expand Down Expand Up @@ -90,7 +91,7 @@ public boolean onCommand(@NotNull Plugin plugin, @NotNull CommandSender sender,
*/
private void handleDeposit(Player player, UUID islandId, String[] args) {
// Permission pour deposit
if (!player.hasPermission("skyllia.bank.deposit")) {
if (!PermissionImp.hasPermission(player, "skyllia.bank.deposit")) {
LanguageToml.sendMessage(
player,
SkylliaBank.getConfiguration().getString(
Expand Down Expand Up @@ -227,7 +228,7 @@ private void handleDeposit(Player player, UUID islandId, String[] args) {
*/
private void handleWithdraw(Player player, UUID islandId, String[] args) {
// Permission pour withdraw
if (!player.hasPermission("skyllia.bank.withdraw")) {
if (!PermissionImp.hasPermission(player, "skyllia.bank.withdraw")) {
LanguageToml.sendMessage(
player,
SkylliaBank.getConfiguration().getString(
Expand Down Expand Up @@ -372,7 +373,7 @@ private void handleWithdraw(Player player, UUID islandId, String[] args) {
*/
private void handleBalance(Player player, UUID islandId) {
// Permission pour voir le solde
if (!player.hasPermission("skyllia.bank.balance")) {
if (!PermissionImp.hasPermission(player, "skyllia.bank.balance")) {
LanguageToml.sendMessage(
player,
SkylliaBank.getConfiguration().getString(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package fr.euphyllia.skylliainfo;

import fr.euphyllia.skyllia.api.PermissionImp;
import fr.euphyllia.skyllia.api.SkylliaAPI;
import fr.euphyllia.skyllia.api.commands.SubCommandInterface;
import fr.euphyllia.skyllia.api.skyblock.Island;
Expand Down Expand Up @@ -43,7 +44,7 @@ public boolean onCommand(@NotNull Plugin plugin, @NotNull CommandSender sender,

UUID playerId = null;

if (sender.hasPermission("skyllia.extensions.commands.is_info") && arg.length == 1) {
if (PermissionImp.hasPermission(sender, "skyllia.extensions.commands.is_info") && arg.length == 1) {
playerId = Bukkit.getPlayerUniqueId(arg[0]);
}
if (playerId == null) {
Expand Down
2 changes: 1 addition & 1 deletion addons/SkylliaOre/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ plugins {
}

group = "fr.euphyllia.skyllia";
version = "1.1";
version = "1.2";

repositories {
maven("https://repo.oraxen.com/releases")
Expand Down
40 changes: 18 additions & 22 deletions addons/SkylliaOre/src/main/java/fr/euphyllia/skylliaore/Cache.java
Original file line number Diff line number Diff line change
@@ -1,48 +1,44 @@
package fr.euphyllia.skylliaore;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.github.benmanes.caffeine.cache.AsyncLoadingCache;
import com.github.benmanes.caffeine.cache.Caffeine;
import fr.euphyllia.skylliaore.api.Generator;
import fr.euphyllia.skylliaore.database.MariaDBInit;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;

import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class Cache {

private static final Logger logger = LogManager.getLogger(Cache.class);

private final LoadingCache<UUID, Generator> generatorLoadingCache = CacheBuilder.newBuilder()
private final AsyncLoadingCache<UUID, Generator> generatorLoadingCache = Caffeine.newBuilder()
.expireAfterWrite(5, TimeUnit.SECONDS)
.build(
new CacheLoader<>() {
@Override
public @NotNull Generator load(@NotNull UUID cache) {
try {
return MariaDBInit.getMariaDbGenerator().getGenIsland(cache).get(2, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
logger.error(e.getMessage(), e);
return Main.getDefaultConfig().getDefaultGenerator();
}
}
}
);
.buildAsync((islandId, executor) -> {
CompletableFuture<Generator> future = MariaDBInit.getMariaDbGenerator().getGenIsland(islandId);
return future.exceptionally(e -> {
logger.error("Error loading generator for island {}: {}", islandId, e.getMessage(), e);
return Main.getDefaultConfig().getDefaultGenerator();
});
});

public Cache() {

}

public Generator getGeneratorIsland(UUID island) {
public Generator getGeneratorIsland(UUID islandId) {
try {
return generatorLoadingCache.get(island);
return generatorLoadingCache.get(islandId).get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // Réinitialiser le statut d'interruption
logger.error("Thread interrupted while accessing cache for island {}: {}", islandId, e.getMessage(), e);
return Main.getDefaultConfig().getDefaultGenerator();
} catch (ExecutionException e) {
logger.error(e.getMessage(), e);
logger.error("Error accessing cache for island {}: {}", islandId, e.getMessage(), e);
return Main.getDefaultConfig().getDefaultGenerator();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,19 @@

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public record Generator(String name, List<String> replaceBlocks, List<String> worlds,
public record Generator(String name, Set<String> replaceBlocks, Set<String> worlds,
Map<String, Double> blockChances) {

}
public Generator(String name, List<String> replaceBlocks, List<String> worlds,
Map<String, Double> blockChances) {
this(
name,
replaceBlocks.stream().map(String::toLowerCase).collect(Collectors.toUnmodifiableSet()),
worlds.stream().map(String::toLowerCase).collect(Collectors.toUnmodifiableSet()),
Map.copyOf(blockChances)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import fr.euphyllia.skyllia.api.skyblock.Island;
import fr.euphyllia.skylliaore.Main;
import fr.euphyllia.skylliaore.api.Generator;
import fr.euphyllia.skylliaore.utils.OptimizedGenerator;
import io.th0rgal.oraxen.api.OraxenBlocks;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.data.BlockData;
Expand All @@ -15,68 +15,88 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.Random;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom;
import java.util.Collections;

public class OreEvent implements Listener {

private static final Logger log = LoggerFactory.getLogger(OreEvent.class);
private static final boolean isOraxenLoaded = Main.isOraxenLoaded();
private static final ConcurrentHashMap<String, BlockData> blockDataCache = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<String, OptimizedGenerator> optimizedGeneratorCache = new ConcurrentHashMap<>();

@EventHandler
public void onBlockForm(final BlockFormEvent event) {
if (event.isCancelled()) return;

Location location = event.getBlock().getLocation();
World world = location.getWorld();
World world = event.getBlock().getWorld();

if (!SkylliaAPI.isWorldSkyblock(world)) return;

Island island = SkylliaAPI.getIslandByChunk(location.getChunk());
Island island = SkylliaAPI.getIslandByChunk(event.getBlock().getChunk());
if (island == null) return;

handleBlockFormation(event, world, island);
}

private void handleBlockFormation(BlockFormEvent event, World world, Island island) {
String worldName = world.getName();
String worldName = world.getName().toLowerCase();
Material blockType = event.getNewState().getType();

Generator generator = Main.getCache().getGeneratorIsland(island.getId());
if (generator == null) return;

if (generator.worlds().contains(worldName)) {
for (String replace : generator.replaceBlocks()) {
if (replace.equalsIgnoreCase(blockType.name())) {
BlockData blockByChance = getBlockByChance(generator.blockChances());
event.getNewState().setBlockData(blockByChance);
break;
}
// Utiliser un cache pour OptimizedGenerator
OptimizedGenerator optimizedGenerator = optimizedGeneratorCache.computeIfAbsent(generator.name(),
name -> new OptimizedGenerator(generator));

if (optimizedGenerator.getGenerator().worlds().contains(worldName)) {
String blockName = blockType.name().toLowerCase();
if (optimizedGenerator.getGenerator().replaceBlocks().contains(blockName)) {
BlockData blockByChance = getBlockByChance(optimizedGenerator);
event.getNewState().setBlockData(blockByChance);
}
}
}

private BlockData getBlockByChance(Map<String, Double> blockChances) {
double totalChance = blockChances.values().stream().mapToDouble(i -> i).sum();
double randomChance = new Random().nextDouble() * totalChance;

double currentChance = 0;
for (Map.Entry<String, Double> entry : blockChances.entrySet()) {
currentChance += entry.getValue();
if (randomChance < currentChance) {
try {
if (entry.getKey().startsWith("oraxen:") && Main.isOraxenLoaded()) {
String oraxenBlock = entry.getKey().split(":")[1];
BlockData data = OraxenBlocks.getOraxenBlockData(oraxenBlock);
if (data == null) continue;
return data;
} else {
return Material.valueOf(entry.getKey().toUpperCase()).createBlockData();
}
} catch (Exception exception) {
log.error("{} is not a block Minecraft or Oraxen", entry.getKey());
return Material.COBBLESTONE.createBlockData();
private BlockData getBlockByChance(OptimizedGenerator optimizedGenerator) {
double randomChance = ThreadLocalRandom.current().nextDouble() * optimizedGenerator.getTotalChance();
List<OptimizedGenerator.BlockProbability> cumulativeProbabilities = optimizedGenerator.getCumulativeProbabilities();

// Recherche binaire
int index = Collections.binarySearch(cumulativeProbabilities, new OptimizedGenerator.BlockProbability("", randomChance),
Comparator.comparingDouble(OptimizedGenerator.BlockProbability::cumulativeChance));

if (index < 0) {
index = -index - 1;
}

if (index >= 0 && index < cumulativeProbabilities.size()) {
return getCachedBlockData(cumulativeProbabilities.get(index).blockKey());
}

return Material.COBBLESTONE.createBlockData(); // Bloc par défaut
}

private BlockData getCachedBlockData(String key) {
return blockDataCache.computeIfAbsent(key, k -> {
try {
if (k.startsWith("oraxen:") && isOraxenLoaded) {
String oraxenBlock = k.substring("oraxen:".length());
BlockData data = OraxenBlocks.getOraxenBlockData(oraxenBlock);
if (data != null) return data;
} else {
return Material.valueOf(k.toUpperCase()).createBlockData();
}
} catch (Exception e) {
if (log.isErrorEnabled()) {
log.error("{} is not a valid block in Minecraft or Oraxen", k);
}
}
}
return Material.COBBLESTONE.createBlockData(); // Default block if no match is found
return Material.COBBLESTONE.createBlockData();
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package fr.euphyllia.skylliaore.utils;

import fr.euphyllia.skylliaore.api.Generator;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

public class OptimizedGenerator {
private final Generator generator;
private final List<BlockProbability> cumulativeProbabilities;
private final double totalChance;

public OptimizedGenerator(Generator generator) {
this.generator = generator;
this.cumulativeProbabilities = new ArrayList<>();
double cumulative = 0.0;
for (Map.Entry<String, Double> entry : generator.blockChances().entrySet()) {
cumulative += entry.getValue();
cumulativeProbabilities.add(new BlockProbability(entry.getKey(), cumulative));
}
this.cumulativeProbabilities.sort(Comparator.comparingDouble(BlockProbability::cumulativeChance));
this.totalChance = cumulative;
}

public Generator getGenerator() {
return generator;
}

public List<BlockProbability> getCumulativeProbabilities() {
return cumulativeProbabilities;
}

public double getTotalChance() {
return totalChance;
}

public record BlockProbability(String blockKey, double cumulativeChance) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
* }
*
* // Example 3: Preventing the world change under certain conditions
* if (player.hasPedrmission("skyblock.portal.override")) {
* if (player.hasPermission("skyblock.portal.override")) {
* player.sendMessage("You do not have permission to change to this world.");
* event.setCancelled(true);
* }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
* System.out.println("Player " + player.getName() + " is teleporting to spawn at location " + destination + ".");
*
* // Example 2: Modifying the final teleport location
* if (player.hasPedrmission("skyblock.teleport.vip")) {
* if (player.hasPermission("skyblock.teleport.vip")) {
* Location vipLocation = destination.clone().add(10, 0, 10); // Offset for VIP players
* event.setFinalLocation(vipLocation);
* player.sendMessage("VIP teleportation: Your spawn location has been adjusted.");
Expand Down

0 comments on commit cf84d9a

Please sign in to comment.