package tc.oc.commons.bukkit.raindrops;
import javax.annotation.Nullable;
import javax.inject.Inject;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.event.EventBus;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import java.time.Duration;
import tc.oc.api.bukkit.users.BukkitUserStore;
import tc.oc.api.docs.PlayerId;
import tc.oc.api.users.UserService;
import tc.oc.commons.bukkit.chat.Audiences;
import tc.oc.commons.bukkit.util.NMSHacks;
import tc.oc.commons.bukkit.util.SyncPlayerExecutorFactory;
import tc.oc.commons.core.chat.Audience;
import tc.oc.commons.core.chat.Component;
public class RaindropUtil {
@Inject private static Plugin plugin;
@Inject private static BukkitUserStore userStore;
@Inject private static UserService userService;
@Inject private static SyncPlayerExecutorFactory playerExecutorFactory;
@Inject private static EventBus eventBus;
@Inject private static Audiences audiences;
public static int useMultiplier(int count, int multiplier) {
return (int) (count * multiplier / 100f);
}
public static int calculateMultiplier(PlayerId playerId) {
final Player player = userStore.find(playerId);
int multiplier = RaindropConstants.MULTIPLIER_BASE;
if(player != null) {
for(int i = RaindropConstants.MULTIPLIER_MAX; i > 0; i = i - RaindropConstants.MULTIPLIER_INCREMENT) {
if(player.hasPermission("raindrops.multiplier." + i)) {
multiplier = i;
break;
}
}
}
return multiplier;
}
public static int calculateRaindrops(PlayerId playerId, int delta, boolean useMultiplier) {
if(delta == 0) return 0;
if(useMultiplier) {
delta = useMultiplier(delta, calculateMultiplier(playerId));
}
return delta;
}
public static void giveRaindrops(PlayerId playerId, int count, @Nullable RaindropResult result) {
giveRaindrops(playerId, count, result, null);
}
public static void giveRaindrops(PlayerId playerId, int count, @Nullable RaindropResult result, @Nullable BaseComponent reason) {
giveRaindrops(playerId, count, result, reason, true);
}
public static void giveRaindrops(PlayerId playerId, int delta, @Nullable RaindropResult result, @Nullable BaseComponent reason, boolean useMultiplier) {
giveRaindrops(playerId, delta, result, reason, useMultiplier, true);
}
public static void giveRaindrops(PlayerId playerId, int delta, @Nullable RaindropResult result, @Nullable BaseComponent reason, boolean useMultiplier, boolean save) {
giveRaindrops(playerId, delta, result, reason, useMultiplier, save, true);
}
public static void giveRaindrops(PlayerId playerId, int delta, @Nullable RaindropResult result, @Nullable BaseComponent reason, boolean useMultiplier, boolean save, boolean show) {
if(delta == 0) return;
final int multiplier;
if(useMultiplier) {
multiplier = calculateMultiplier(playerId);
delta = useMultiplier(delta, multiplier);
} else {
multiplier = RaindropConstants.MULTIPLIER_BASE;
}
giveRaindrops(playerId, delta, multiplier, result, reason, save, show);
}
public static void giveRaindrops(PlayerId playerId, int delta, int multiplier, @Nullable RaindropResult result, @Nullable BaseComponent reason, boolean save) {
giveRaindrops(playerId, delta, multiplier, result, reason, save, true);
}
public static void giveRaindrops(PlayerId playerId, int delta, int multiplier, @Nullable RaindropResult result, @Nullable BaseComponent reason, boolean save, boolean show) {
final int countBefore = userStore.getUser(playerId).raindrops();
if(countBefore + delta < 0) {
if(result != null) {
result.setSuccess(false);
}
return;
}
if(save) {
final int finalDelta = delta;
playerExecutorFactory.queued(playerId).callback(
userService.creditRaindrops(playerId, finalDelta),
(player, update) -> {
if(update.success()) {
showRaindrops(player, finalDelta, multiplier, reason, show);
}
if(result != null) {
result.setSuccess(update.success());
}
}
);
} else {
final Player player = userStore.find(playerId);
if(player != null) {
showRaindrops(player, delta, multiplier, reason, show);
}
if(result != null) {
result.setSuccess(true);
}
}
}
public static void showRaindrops(Player player, int delta, int multiplier, @Nullable BaseComponent reason) {
showRaindrops(player, delta, multiplier, reason, true);
}
public static void showRaindrops(Player player, int delta, int multiplier, @Nullable BaseComponent reason, boolean show) {
eventBus.callEvent(new PlayerRecieveRaindropsEvent(player, delta, multiplier, reason));
if (show) {
final Audience audience = audiences.get(player);
audience.sendMessage(raindropsMessage(delta, multiplier, reason));
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1f, 1.5f);
raindropDisplay(player, delta);
}
}
public static void raindropDisplay(final Player player, int count) {
if(count == 1) {
count = 2;
} else if(count > 12) {
count = 12;
}
NMSHacks.showFakeItems(plugin,
player,
player.getLocation().add(0, 2, 0),
new ItemStack(Material.GHAST_TEAR),
count,
Duration.ofSeconds(3));
}
private static BaseComponent raindropsMessage(int count, int multiplier, @Nullable BaseComponent reason) {
Component message = new Component(ChatColor.GRAY);
message.extra(new Component((count > 0 ? "+" : "") + count, ChatColor.GREEN, ChatColor.BOLD),
new Component(" Raindrop" + (count == 1 || count == -1 ? "" : "s"), ChatColor.AQUA));
if(multiplier != 100) {
message.extra(new Component(" | ", ChatColor.DARK_PURPLE),
new Component((multiplier / 100f) + "x", ChatColor.GOLD, ChatColor.ITALIC));
}
if(reason != null) {
message.extra(new Component(" | ", ChatColor.DARK_PURPLE),
reason);
}
return message;
}
}