try recreate vanilla restocking mechanic

This commit is contained in:
xGinko 2024-09-02 01:49:14 +02:00
parent 04d6cf604c
commit 72e2673248
33 changed files with 135 additions and 128 deletions

View File

@ -6,7 +6,7 @@
<groupId>me.xginko</groupId> <groupId>me.xginko</groupId>
<artifactId>VillagerOptimizer</artifactId> <artifactId>VillagerOptimizer</artifactId>
<version>1.6.2</version> <version>1.7.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>VillagerOptimizer</name> <name>VillagerOptimizer</name>
@ -187,7 +187,7 @@
<dependency> <dependency>
<groupId>com.github.cryptomorin</groupId> <groupId>com.github.cryptomorin</groupId>
<artifactId>XSeries</artifactId> <artifactId>XSeries</artifactId>
<version>11.2.0.1</version> <version>11.2.1</version>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -5,7 +5,7 @@ import com.github.benmanes.caffeine.cache.Caffeine;
import me.xginko.villageroptimizer.commands.VillagerOptimizerCommand; import me.xginko.villageroptimizer.commands.VillagerOptimizerCommand;
import me.xginko.villageroptimizer.config.Config; import me.xginko.villageroptimizer.config.Config;
import me.xginko.villageroptimizer.config.LanguageCache; import me.xginko.villageroptimizer.config.LanguageCache;
import me.xginko.villageroptimizer.enums.Permissions; import me.xginko.villageroptimizer.struct.enums.Permissions;
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
import me.xginko.villageroptimizer.utils.Util; import me.xginko.villageroptimizer.utils.Util;
import me.xginko.villageroptimizer.wrapper.WrappedVillager; import me.xginko.villageroptimizer.wrapper.WrappedVillager;

View File

@ -1,8 +1,8 @@
package me.xginko.villageroptimizer.commands; package me.xginko.villageroptimizer.commands;
import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.utils.Disableable; import me.xginko.villageroptimizer.struct.Disableable;
import me.xginko.villageroptimizer.utils.Enableable; import me.xginko.villageroptimizer.struct.Enableable;
import org.bukkit.command.CommandException; import org.bukkit.command.CommandException;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.PluginCommand; import org.bukkit.command.PluginCommand;

View File

@ -3,8 +3,8 @@ package me.xginko.villageroptimizer.commands.optimizevillagers;
import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.commands.VillagerOptimizerCommand; import me.xginko.villageroptimizer.commands.VillagerOptimizerCommand;
import me.xginko.villageroptimizer.config.Config; import me.xginko.villageroptimizer.config.Config;
import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.struct.enums.OptimizationType;
import me.xginko.villageroptimizer.enums.Permissions; import me.xginko.villageroptimizer.struct.enums.Permissions;
import me.xginko.villageroptimizer.events.VillagerOptimizeEvent; import me.xginko.villageroptimizer.events.VillagerOptimizeEvent;
import me.xginko.villageroptimizer.utils.KyoriUtil; import me.xginko.villageroptimizer.utils.KyoriUtil;
import me.xginko.villageroptimizer.wrapper.WrappedVillager; import me.xginko.villageroptimizer.wrapper.WrappedVillager;

View File

@ -2,8 +2,8 @@ package me.xginko.villageroptimizer.commands.unoptimizevillagers;
import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.commands.VillagerOptimizerCommand; import me.xginko.villageroptimizer.commands.VillagerOptimizerCommand;
import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.struct.enums.OptimizationType;
import me.xginko.villageroptimizer.enums.Permissions; import me.xginko.villageroptimizer.struct.enums.Permissions;
import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent; import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent;
import me.xginko.villageroptimizer.utils.KyoriUtil; import me.xginko.villageroptimizer.utils.KyoriUtil;
import me.xginko.villageroptimizer.wrapper.WrappedVillager; import me.xginko.villageroptimizer.wrapper.WrappedVillager;

View File

@ -5,7 +5,7 @@ import me.xginko.villageroptimizer.commands.VillagerOptimizerCommand;
import me.xginko.villageroptimizer.commands.villageroptimizer.subcommands.DisableSubCmd; import me.xginko.villageroptimizer.commands.villageroptimizer.subcommands.DisableSubCmd;
import me.xginko.villageroptimizer.commands.villageroptimizer.subcommands.ReloadSubCmd; import me.xginko.villageroptimizer.commands.villageroptimizer.subcommands.ReloadSubCmd;
import me.xginko.villageroptimizer.commands.villageroptimizer.subcommands.VersionSubCmd; import me.xginko.villageroptimizer.commands.villageroptimizer.subcommands.VersionSubCmd;
import me.xginko.villageroptimizer.enums.Permissions; import me.xginko.villageroptimizer.struct.enums.Permissions;
import me.xginko.villageroptimizer.utils.KyoriUtil; import me.xginko.villageroptimizer.utils.KyoriUtil;
import me.xginko.villageroptimizer.utils.Util; import me.xginko.villageroptimizer.utils.Util;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;

View File

@ -2,7 +2,7 @@ package me.xginko.villageroptimizer.commands.villageroptimizer.subcommands;
import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.commands.SubCommand; import me.xginko.villageroptimizer.commands.SubCommand;
import me.xginko.villageroptimizer.enums.Permissions; import me.xginko.villageroptimizer.struct.enums.Permissions;
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
import me.xginko.villageroptimizer.utils.KyoriUtil; import me.xginko.villageroptimizer.utils.KyoriUtil;
import me.xginko.villageroptimizer.utils.Util; import me.xginko.villageroptimizer.utils.Util;

View File

@ -2,7 +2,7 @@ package me.xginko.villageroptimizer.commands.villageroptimizer.subcommands;
import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.commands.SubCommand; import me.xginko.villageroptimizer.commands.SubCommand;
import me.xginko.villageroptimizer.enums.Permissions; import me.xginko.villageroptimizer.struct.enums.Permissions;
import me.xginko.villageroptimizer.utils.KyoriUtil; import me.xginko.villageroptimizer.utils.KyoriUtil;
import me.xginko.villageroptimizer.utils.Util; import me.xginko.villageroptimizer.utils.Util;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;

View File

@ -3,7 +3,7 @@ package me.xginko.villageroptimizer.commands.villageroptimizer.subcommands;
import io.papermc.paper.plugin.configuration.PluginMeta; import io.papermc.paper.plugin.configuration.PluginMeta;
import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.commands.SubCommand; import me.xginko.villageroptimizer.commands.SubCommand;
import me.xginko.villageroptimizer.enums.Permissions; import me.xginko.villageroptimizer.struct.enums.Permissions;
import me.xginko.villageroptimizer.utils.KyoriUtil; import me.xginko.villageroptimizer.utils.KyoriUtil;
import me.xginko.villageroptimizer.utils.Util; import me.xginko.villageroptimizer.utils.Util;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;

View File

@ -118,13 +118,13 @@ public class Config {
return this.config.getInteger(path, def); return this.config.getInteger(path, def);
} }
public @NotNull List<String> getList(@NotNull String path, @NotNull List<String> def, @NotNull String comment) { public @NotNull <T> List<T> getList(@NotNull String path, @NotNull List<T> def, @NotNull String comment) {
this.config.addDefault(path, def, comment); this.config.addDefault(path, def, comment);
return this.config.getStringList(path); return this.config.getList(path);
} }
public @NotNull List<String> getList(@NotNull String path, @NotNull List<String> def) { public @NotNull <T> List<T> getList(@NotNull String path, @NotNull List<T> def) {
this.config.addDefault(path, def); this.config.addDefault(path, def);
return this.config.getStringList(path); return this.config.getList(path);
} }
} }

View File

@ -1,7 +1,7 @@
package me.xginko.villageroptimizer.events; package me.xginko.villageroptimizer.events;
import me.xginko.villageroptimizer.wrapper.WrappedVillager; import me.xginko.villageroptimizer.wrapper.WrappedVillager;
import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.struct.enums.OptimizationType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
import org.bukkit.event.Event; import org.bukkit.event.Event;

View File

@ -1,7 +1,7 @@
package me.xginko.villageroptimizer.events; package me.xginko.villageroptimizer.events;
import me.xginko.villageroptimizer.wrapper.WrappedVillager; import me.xginko.villageroptimizer.wrapper.WrappedVillager;
import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.struct.enums.OptimizationType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
import org.bukkit.event.Event; import org.bukkit.event.Event;

View File

@ -1,4 +1,4 @@
package me.xginko.villageroptimizer.utils; package me.xginko.villageroptimizer.logging;
import net.kyori.adventure.text.logger.slf4j.ComponentLogger; import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
import net.kyori.adventure.text.logger.slf4j.ComponentLoggerProvider; import net.kyori.adventure.text.logger.slf4j.ComponentLoggerProvider;

View File

@ -1,4 +1,4 @@
package me.xginko.villageroptimizer.utils; package me.xginko.villageroptimizer.logging;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TranslatableComponent; import net.kyori.adventure.text.TranslatableComponent;

View File

@ -1,7 +1,7 @@
package me.xginko.villageroptimizer.modules; package me.xginko.villageroptimizer.modules;
import com.cryptomorin.xseries.XEntityType; import com.cryptomorin.xseries.XEntityType;
import me.xginko.villageroptimizer.utils.ExpiringSet; import me.xginko.villageroptimizer.struct.models.ExpiringSet;
import me.xginko.villageroptimizer.utils.LocationUtil; import me.xginko.villageroptimizer.utils.LocationUtil;
import me.xginko.villageroptimizer.utils.Util; import me.xginko.villageroptimizer.utils.Util;
import me.xginko.villageroptimizer.wrapper.WrappedVillager; import me.xginko.villageroptimizer.wrapper.WrappedVillager;

View File

@ -3,8 +3,8 @@ package me.xginko.villageroptimizer.modules;
import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Cache;
import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.config.Config; import me.xginko.villageroptimizer.config.Config;
import me.xginko.villageroptimizer.utils.Disableable; import me.xginko.villageroptimizer.struct.Disableable;
import me.xginko.villageroptimizer.utils.Enableable; import me.xginko.villageroptimizer.struct.Enableable;
import me.xginko.villageroptimizer.wrapper.WrappedVillager; import me.xginko.villageroptimizer.wrapper.WrappedVillager;
import org.bukkit.entity.Villager; import org.bukkit.entity.Villager;
import org.reflections.Reflections; import org.reflections.Reflections;

View File

@ -1,7 +1,7 @@
package me.xginko.villageroptimizer.modules.gameplay; package me.xginko.villageroptimizer.modules.gameplay;
import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.enums.Permissions; import me.xginko.villageroptimizer.struct.enums.Permissions;
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
import me.xginko.villageroptimizer.utils.KyoriUtil; import me.xginko.villageroptimizer.utils.KyoriUtil;
import me.xginko.villageroptimizer.wrapper.WrappedVillager; import me.xginko.villageroptimizer.wrapper.WrappedVillager;

View File

@ -2,14 +2,13 @@ package me.xginko.villageroptimizer.modules.gameplay;
import com.cryptomorin.xseries.XEntityType; import com.cryptomorin.xseries.XEntityType;
import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.enums.Permissions;
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
import me.xginko.villageroptimizer.struct.enums.Permissions;
import me.xginko.villageroptimizer.utils.KyoriUtil; import me.xginko.villageroptimizer.utils.KyoriUtil;
import me.xginko.villageroptimizer.utils.LocationUtil; import me.xginko.villageroptimizer.utils.LocationUtil;
import me.xginko.villageroptimizer.utils.Util; import me.xginko.villageroptimizer.utils.Util;
import me.xginko.villageroptimizer.wrapper.WrappedVillager; import me.xginko.villageroptimizer.wrapper.WrappedVillager;
import net.kyori.adventure.text.TextReplacementConfig; import net.kyori.adventure.text.TextReplacementConfig;
import org.bukkit.entity.Player;
import org.bukkit.entity.Villager; import org.bukkit.entity.Villager;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
@ -18,10 +17,14 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEntityEvent;
import java.time.Duration; import java.time.Duration;
import java.util.Arrays;
import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;
public class RestockOptimizedTrades extends VillagerOptimizerModule implements Listener { public class RestockOptimizedTrades extends VillagerOptimizerModule implements Listener {
private final long restock_delay_millis; private final SortedSet<Long> restockDayTimes;
private final boolean log_enabled, notify_player; private final boolean log_enabled, notify_player;
public RestockOptimizedTrades() { public RestockOptimizedTrades() {
@ -29,8 +32,10 @@ public class RestockOptimizedTrades extends VillagerOptimizerModule implements L
config.master().addComment(configPath, config.master().addComment(configPath,
"This is for automatic restocking of trades for optimized villagers. Optimized Villagers\n" + "This is for automatic restocking of trades for optimized villagers. Optimized Villagers\n" +
"don't have enough AI to restock their trades naturally, so this is here as a workaround."); "don't have enough AI to restock their trades naturally, so this is here as a workaround.");
this.restock_delay_millis = config.getInt(configPath + ".delay-in-ticks", 1000, this.restockDayTimes = new TreeSet<>(Comparator.reverseOrder());
"1 second = 20 ticks. There are 24.000 ticks in a single minecraft day.") * 50L; this.restockDayTimes.addAll(config.getList(configPath + ".restock-times", Arrays.asList(1000L, 13000L),
"At which (tick-)times during the day villagers will restock.\n" +
"There are 24.000 ticks in a single minecraft day."));
this.notify_player = config.getBoolean(configPath + ".notify-player", true, this.notify_player = config.getBoolean(configPath + ".notify-player", true,
"Sends the player a message when the trades were restocked on a clicked villager."); "Sends the player a message when the trades were restocked on a clicked villager.");
this.log_enabled = config.getBoolean(configPath + ".log", false); this.log_enabled = config.getBoolean(configPath + ".log", false);
@ -52,26 +57,50 @@ public class RestockOptimizedTrades extends VillagerOptimizerModule implements L
} }
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onInteract(PlayerInteractEntityEvent event) { private void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
if (event.getRightClicked().getType() != XEntityType.VILLAGER.get()) return; if (event.getRightClicked().getType() != XEntityType.VILLAGER.get()) return;
final WrappedVillager wrapped = wrapperCache.get((Villager) event.getRightClicked(), WrappedVillager::new); WrappedVillager wrapped = wrapperCache.get((Villager) event.getRightClicked(), WrappedVillager::new);
if (!wrapped.isOptimized()) return; if (!wrapped.isOptimized()) return;
final Player player = event.getPlayer(); if (event.getPlayer().hasPermission(Permissions.Bypass.RESTOCK_COOLDOWN.get())) {
final boolean player_bypassing = player.hasPermission(Permissions.Bypass.RESTOCK_COOLDOWN.get()); wrapped.restock();
if (!wrapped.canRestock(restock_delay_millis) && !player_bypassing) return; return;
}
wrapped.restock(); long lastRestockFullTimeTicks = wrapped.getLastRestockFullTime();
wrapped.saveRestockTime(); long currentFullTimeTicks = wrapped.currentFullTimeTicks();
long currentDayTimeTicks = wrapped.currentDayTimeTicks();
if (notify_player && !player_bypassing) { long currentDay = currentFullTimeTicks - currentDayTimeTicks;
long ticksTillRestock = (24000 + currentDay + restockDayTimes.first()) - currentFullTimeTicks;
boolean restocked = false;
for (Long restockDayTime : restockDayTimes) {
long restockTimeToday = currentDay + restockDayTime;
if (currentFullTimeTicks < restockTimeToday || lastRestockFullTimeTicks >= restockTimeToday) {
ticksTillRestock = Math.min(ticksTillRestock, restockTimeToday - currentFullTimeTicks);
continue;
}
wrapped.restock();
wrapped.saveRestockTime();
restocked = true;
break;
}
if (!restocked) return;
if (notify_player) {
final TextReplacementConfig timeLeft = TextReplacementConfig.builder() final TextReplacementConfig timeLeft = TextReplacementConfig.builder()
.matchLiteral("%time%") .matchLiteral("%time%")
.replacement(Util.formatDuration(Duration.ofMillis(wrapped.getRestockCooldownMillis(restock_delay_millis)))) .replacement(Util.formatDuration(Duration.ofMillis(ticksTillRestock * 50L)))
.build(); .build();
VillagerOptimizer.getLang(player.locale()).trades_restocked VillagerOptimizer.getLang(event.getPlayer().locale()).trades_restocked
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(timeLeft))); .forEach(line -> KyoriUtil.sendMessage(event.getPlayer(), line.replaceText(timeLeft)));
} }
if (log_enabled) { if (log_enabled) {

View File

@ -1,6 +1,6 @@
package me.xginko.villageroptimizer.modules.gameplay; package me.xginko.villageroptimizer.modules.gameplay;
import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.struct.enums.OptimizationType;
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
import me.xginko.villageroptimizer.wrapper.WrappedVillager; import me.xginko.villageroptimizer.wrapper.WrappedVillager;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;

View File

@ -2,8 +2,8 @@ package me.xginko.villageroptimizer.modules.optimization;
import com.cryptomorin.xseries.XMaterial; import com.cryptomorin.xseries.XMaterial;
import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.struct.enums.OptimizationType;
import me.xginko.villageroptimizer.enums.Permissions; import me.xginko.villageroptimizer.struct.enums.Permissions;
import me.xginko.villageroptimizer.events.VillagerOptimizeEvent; import me.xginko.villageroptimizer.events.VillagerOptimizeEvent;
import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent; import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent;
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;

View File

@ -3,8 +3,8 @@ package me.xginko.villageroptimizer.modules.optimization;
import com.cryptomorin.xseries.XEntityType; import com.cryptomorin.xseries.XEntityType;
import com.cryptomorin.xseries.XMaterial; import com.cryptomorin.xseries.XMaterial;
import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.struct.enums.OptimizationType;
import me.xginko.villageroptimizer.enums.Permissions; import me.xginko.villageroptimizer.struct.enums.Permissions;
import me.xginko.villageroptimizer.events.VillagerOptimizeEvent; import me.xginko.villageroptimizer.events.VillagerOptimizeEvent;
import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent; import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent;
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;

View File

@ -1,8 +1,8 @@
package me.xginko.villageroptimizer.modules.optimization; package me.xginko.villageroptimizer.modules.optimization;
import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.struct.enums.OptimizationType;
import me.xginko.villageroptimizer.enums.Permissions; import me.xginko.villageroptimizer.struct.enums.Permissions;
import me.xginko.villageroptimizer.events.VillagerOptimizeEvent; import me.xginko.villageroptimizer.events.VillagerOptimizeEvent;
import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent; import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent;
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;

View File

@ -1,4 +1,4 @@
package me.xginko.villageroptimizer.utils; package me.xginko.villageroptimizer.struct;
public interface Disableable { public interface Disableable {
void disable(); void disable();

View File

@ -1,4 +1,4 @@
package me.xginko.villageroptimizer.utils; package me.xginko.villageroptimizer.struct;
public interface Enableable { public interface Enableable {
void enable(); void enable();

View File

@ -1,4 +1,4 @@
package me.xginko.villageroptimizer.enums; package me.xginko.villageroptimizer.struct.enums;
import net.kyori.adventure.key.Namespaced; import net.kyori.adventure.key.Namespaced;
import org.bukkit.Keyed; import org.bukkit.Keyed;
@ -52,7 +52,7 @@ public final class Keyring {
OPTIMIZATION_TYPE("optimization-type"), OPTIMIZATION_TYPE("optimization-type"),
LAST_OPTIMIZE_SYSTIME_MILLIS("last-optimize"), LAST_OPTIMIZE_SYSTIME_MILLIS("last-optimize"),
LAST_LEVELUP_SYSTIME_MILLIS("last-levelup"), LAST_LEVELUP_SYSTIME_MILLIS("last-levelup"),
LAST_RESTOCK_SYSTIME_MILLIS("last-restock-systime"); LAST_RESTOCK_WORLD_FULLTIME("last-restock-full-time");
private final @NotNull NamespacedKey key; private final @NotNull NamespacedKey key;
@ -69,7 +69,7 @@ public final class Keyring {
public enum AntiVillagerLag implements Keyed { public enum AntiVillagerLag implements Keyed {
NEXT_OPTIMIZATION_SYSTIME_SECONDS("cooldown"), // Returns LONG -> (System.currentTimeMillis() / 1000) + cooldown seconds NEXT_OPTIMIZATION_SYSTIME_SECONDS("cooldown"), // Returns LONG -> (System.currentTimeMillis() / 1000) + cooldown seconds
LAST_RESTOCK_WORLDFULLTIME("time"), // Returns LONG -> villager.getWorld().getFullTime() LAST_RESTOCK_WORLD_FULLTIME("time"), // Returns LONG -> villager.getWorld().getFullTime()
NEXT_LEVELUP_SYSTIME_SECONDS("levelCooldown"), // Returns LONG -> (System.currentTimeMillis() / 1000) + cooldown seconds NEXT_LEVELUP_SYSTIME_SECONDS("levelCooldown"), // Returns LONG -> (System.currentTimeMillis() / 1000) + cooldown seconds
OPTIMIZED_ANY("Marker"), // Returns STRING -> "AVL" OPTIMIZED_ANY("Marker"), // Returns STRING -> "AVL"
OPTIMIZED_BLOCK("disabledByBlock"), // Returns STRING -> key().toString() OPTIMIZED_BLOCK("disabledByBlock"), // Returns STRING -> key().toString()

View File

@ -1,4 +1,4 @@
package me.xginko.villageroptimizer.enums; package me.xginko.villageroptimizer.struct.enums;
public enum OptimizationType { public enum OptimizationType {
COMMAND, COMMAND,

View File

@ -1,4 +1,4 @@
package me.xginko.villageroptimizer.enums; package me.xginko.villageroptimizer.struct.enums;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.permissions.Permission; import org.bukkit.permissions.Permission;

View File

@ -1,4 +1,4 @@
package me.xginko.villageroptimizer.utils; package me.xginko.villageroptimizer.struct.models;
import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.Caffeine;

View File

@ -1,8 +1,8 @@
package me.xginko.villageroptimizer.wrapper; package me.xginko.villageroptimizer.wrapper;
import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.enums.Keyring; import me.xginko.villageroptimizer.struct.enums.Keyring;
import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.struct.enums.OptimizationType;
import org.bukkit.entity.Villager; import org.bukkit.entity.Villager;
import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataContainer;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -68,29 +68,17 @@ public abstract class PDCWrapper {
public abstract long getOptimizeCooldownMillis(long cooldown_millis); public abstract long getOptimizeCooldownMillis(long cooldown_millis);
/** /**
* For convenience so the remaining millis since the last stored restock time * Gets the time of the day in ticks when the entity was last restocked.
* can be easily calculated. * This value is affected by /time set
* * @return The time of the minecraft day (in ticks) when the villager was last restocked
* @param cooldown_millis The configured cooldown in milliseconds you want to check against.
* @return True if the villager has been loaded long enough.
*/ */
public abstract boolean canRestock(long cooldown_millis); public abstract long getLastRestockFullTime();
/** /**
* Saves the time of when the entity was last restocked. * Saves the time of when the entity was last restocked.
*/ */
public abstract void saveRestockTime(); public abstract void saveRestockTime();
/**
* For convenience so the remaining millis since the last stored restock time
* can be easily calculated.
* This enables new configured cooldowns to instantly apply instead of them being persistent.
*
* @param cooldown_millis The configured cooldown in milliseconds you want to check against.
* @return The time left in millis until the villager can be restocked again.
*/
public abstract long getRestockCooldownMillis(long cooldown_millis);
/** /**
* @param cooldown_millis The configured cooldown in milliseconds you want to check against. * @param cooldown_millis The configured cooldown in milliseconds you want to check against.
* @return Whether the villager can be leveled up or not with the checked milliseconds * @return Whether the villager can be leveled up or not with the checked milliseconds

View File

@ -1,8 +1,8 @@
package me.xginko.villageroptimizer.wrapper; package me.xginko.villageroptimizer.wrapper;
import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.enums.Keyring; import me.xginko.villageroptimizer.struct.enums.Keyring;
import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.struct.enums.OptimizationType;
import org.bukkit.entity.Villager; import org.bukkit.entity.Villager;
import org.bukkit.persistence.PersistentDataType; import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -99,21 +99,16 @@ public final class PDCWrapperAVL extends PDCWrapper {
} }
@Override @Override
public boolean canRestock(long cooldown_millis) { public long getLastRestockFullTime() {
return !dataContainer.has(Keyring.AntiVillagerLag.LAST_RESTOCK_WORLDFULLTIME.getKey(), PersistentDataType.LONG) if (dataContainer.has(Keyring.AntiVillagerLag.LAST_RESTOCK_WORLD_FULLTIME.getKey(), PersistentDataType.LONG)) {
|| villager.getWorld().getFullTime() > dataContainer.get(Keyring.AntiVillagerLag.LAST_RESTOCK_WORLDFULLTIME.getKey(), PersistentDataType.LONG); return dataContainer.get(Keyring.AntiVillagerLag.LAST_RESTOCK_WORLD_FULLTIME.getKey(), PersistentDataType.LONG);
}
return 0L;
} }
@Override @Override
public void saveRestockTime() { public void saveRestockTime() {
dataContainer.set(Keyring.AntiVillagerLag.LAST_RESTOCK_WORLDFULLTIME.getKey(), PersistentDataType.LONG, villager.getWorld().getFullTime()); dataContainer.set(Keyring.AntiVillagerLag.LAST_RESTOCK_WORLD_FULLTIME.getKey(), PersistentDataType.LONG, villager.getWorld().getFullTime());
}
@Override
public long getRestockCooldownMillis(long cooldown_millis) {
if (dataContainer.has(Keyring.AntiVillagerLag.LAST_RESTOCK_WORLDFULLTIME.getKey(), PersistentDataType.LONG))
return (villager.getWorld().getFullTime() - dataContainer.get(Keyring.AntiVillagerLag.LAST_RESTOCK_WORLDFULLTIME.getKey(), PersistentDataType.LONG)) * 50L;
return cooldown_millis;
} }
@Override @Override

View File

@ -1,8 +1,8 @@
package me.xginko.villageroptimizer.wrapper; package me.xginko.villageroptimizer.wrapper;
import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.enums.Keyring; import me.xginko.villageroptimizer.struct.enums.Keyring;
import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.struct.enums.OptimizationType;
import org.bukkit.entity.Villager; import org.bukkit.entity.Villager;
import org.bukkit.persistence.PersistentDataType; import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -82,30 +82,16 @@ public final class PDCWrapperVO extends PDCWrapper {
} }
@Override @Override
public boolean canRestock(long cooldown_millis) { public long getLastRestockFullTime() {
return getLastRestock() + cooldown_millis <= System.currentTimeMillis(); if (dataContainer.has(Keyring.VillagerOptimizer.LAST_RESTOCK_WORLD_FULLTIME.getKey(), PersistentDataType.LONG)) {
} return dataContainer.get(Keyring.VillagerOptimizer.LAST_RESTOCK_WORLD_FULLTIME.getKey(), PersistentDataType.LONG);
@Override
public void saveRestockTime() {
dataContainer.set(Keyring.VillagerOptimizer.LAST_RESTOCK_SYSTIME_MILLIS.getKey(), PersistentDataType.LONG, System.currentTimeMillis());
}
/**
* @return The time when the entity was last restocked.
*/
private long getLastRestock() {
if (dataContainer.has(Keyring.VillagerOptimizer.LAST_RESTOCK_SYSTIME_MILLIS.getKey(), PersistentDataType.LONG)) {
return dataContainer.get(Keyring.VillagerOptimizer.LAST_RESTOCK_SYSTIME_MILLIS.getKey(), PersistentDataType.LONG);
} }
return 0L; return 0L;
} }
@Override @Override
public long getRestockCooldownMillis(long cooldown_millis) { public void saveRestockTime() {
if (dataContainer.has(Keyring.VillagerOptimizer.LAST_RESTOCK_SYSTIME_MILLIS.getKey(), PersistentDataType.LONG)) dataContainer.set(Keyring.VillagerOptimizer.LAST_RESTOCK_WORLD_FULLTIME.getKey(), PersistentDataType.LONG, villager.getWorld().getFullTime());
return System.currentTimeMillis() - (dataContainer.get(Keyring.VillagerOptimizer.LAST_RESTOCK_SYSTIME_MILLIS.getKey(), PersistentDataType.LONG) + cooldown_millis);
return cooldown_millis;
} }
@Override @Override

View File

@ -1,7 +1,8 @@
package me.xginko.villageroptimizer.wrapper; package me.xginko.villageroptimizer.wrapper;
import me.xginko.villageroptimizer.enums.Keyring; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.struct.enums.Keyring;
import me.xginko.villageroptimizer.struct.enums.OptimizationType;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.entity.Villager; import org.bukkit.entity.Villager;
@ -19,13 +20,31 @@ public class WrappedVillager extends PDCWrapper {
this.pdcWrappers = PDCWrapper.forVillager(villager); this.pdcWrappers = PDCWrapper.forVillager(villager);
} }
/**
* Returns a number between 0 and 24000
* is affected by /time set
*/
public long currentDayTimeTicks() {
return villager.getWorld().getTime();
}
/**
* Returns the tick time of the world
* is affected by /time set
*/
public long currentFullTimeTicks() {
return villager.getWorld().getFullTime();
}
/** /**
* Restock all trading recipes. * Restock all trading recipes.
*/ */
public void restock() { public void restock() {
for (MerchantRecipe recipe : villager.getRecipes()) { VillagerOptimizer.scheduling().entitySpecificScheduler(villager).run(() -> {
recipe.setUses(0); for (MerchantRecipe recipe : villager.getRecipes()) {
} recipe.setUses(0);
}
}, null);
} }
/** /**
@ -126,13 +145,12 @@ public class WrappedVillager extends PDCWrapper {
} }
@Override @Override
public boolean canRestock(long cooldown_millis) { public long getLastRestockFullTime() {
long cooldown = 0L;
for (PDCWrapper pdcWrapper : pdcWrappers) { for (PDCWrapper pdcWrapper : pdcWrappers) {
if (!pdcWrapper.canRestock(cooldown_millis)) { cooldown = Math.max(cooldown, pdcWrapper.getLastRestockFullTime());
return false;
}
} }
return true; return cooldown;
} }
@Override @Override
@ -142,15 +160,6 @@ public class WrappedVillager extends PDCWrapper {
} }
} }
@Override
public long getRestockCooldownMillis(long cooldown_millis) {
long cooldown = cooldown_millis;
for (PDCWrapper pdcWrapper : pdcWrappers) {
cooldown = Math.max(cooldown, pdcWrapper.getRestockCooldownMillis(cooldown_millis));
}
return cooldown;
}
@Override @Override
public boolean canLevelUp(long cooldown_millis) { public boolean canLevelUp(long cooldown_millis) {
for (PDCWrapper pdcWrapper : pdcWrappers) { for (PDCWrapper pdcWrapper : pdcWrappers) {

View File

@ -1 +1 @@
me.xginko.villageroptimizer.utils.ComponentLoggerProviderImpl me.xginko.villageroptimizer.logging.ComponentLoggerProviderImpl