fix backwards compatibility issues with MiniMessage and Components
downgrade to java 8 so 1.16 modded servers arent left out
This commit is contained in:
parent
f4a5d2b9fd
commit
6a099ddfe3
30
pom.xml
30
pom.xml
@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>me.xginko.VillagerOptimizer</groupId>
|
||||
<artifactId>VillagerOptimizer</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<version>1.5.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>VillagerOptimizer</name>
|
||||
@ -14,7 +14,7 @@
|
||||
<url>https://github.com/xGinko/VillagerOptimizer</url>
|
||||
|
||||
<properties>
|
||||
<java.version>16</java.version>
|
||||
<java.version>1.8</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
@ -107,51 +107,53 @@
|
||||
<version>1.20.4-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Adventure API for easier cross-version compatibility -->
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-platform-bukkit</artifactId>
|
||||
<version>4.3.2</version>
|
||||
</dependency>
|
||||
<!-- Adventure MiniMessage for parsing fancy tags in lang files -->
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-text-minimessage</artifactId>
|
||||
<version>4.15.0</version>
|
||||
<scope>compile</scope>
|
||||
<version>4.16.0</version>
|
||||
</dependency>
|
||||
<!-- Adventure ComponentLogger for colorful logging -->
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-text-logger-slf4j</artifactId>
|
||||
<version>4.15.0</version>
|
||||
<scope>compile</scope>
|
||||
<version>4.16.0</version>
|
||||
</dependency>
|
||||
<!-- Adventure plaintext serializer for reading unstyled content of components -->
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-text-serializer-plain</artifactId>
|
||||
<version>4.15.0</version>
|
||||
<scope>compile</scope>
|
||||
<version>4.16.0</version>
|
||||
</dependency>
|
||||
<!-- Bukkit bStats -->
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- Enhanced config.yml manager -->
|
||||
<dependency>
|
||||
<groupId>com.github.thatsmusic99</groupId>
|
||||
<artifactId>ConfigurationMaster-API</artifactId>
|
||||
<version>v2.0.0-rc.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- Fast Caching -->
|
||||
<!-- Fast Caching (Needs to be 2.9.3 for java 8 support) -->
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
<version>3.1.8</version>
|
||||
<scope>compile</scope>
|
||||
<version>2.9.3</version>
|
||||
</dependency>
|
||||
<!-- Folia Support -->
|
||||
<dependency>
|
||||
<groupId>com.tcoded</groupId>
|
||||
<artifactId>FoliaLib</artifactId>
|
||||
<version>0.3.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -2,10 +2,8 @@ package me.xginko.villageroptimizer;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Villager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.UUID;
|
||||
@ -23,11 +21,6 @@ public final class VillagerCache {
|
||||
return this.villagerCache.asMap();
|
||||
}
|
||||
|
||||
public @Nullable WrappedVillager get(@NotNull UUID uuid) {
|
||||
WrappedVillager wrappedVillager = this.villagerCache.getIfPresent(uuid);
|
||||
return wrappedVillager == null && Bukkit.getEntity(uuid) instanceof Villager villager ? this.add(villager) : wrappedVillager;
|
||||
}
|
||||
|
||||
public @NotNull WrappedVillager getOrAdd(@NotNull Villager villager) {
|
||||
WrappedVillager wrappedVillager = this.villagerCache.getIfPresent(villager.getUniqueId());
|
||||
return wrappedVillager == null ? this.add(new WrappedVillager(villager)) : this.add(wrappedVillager);
|
||||
|
@ -5,6 +5,7 @@ import me.xginko.villageroptimizer.commands.VillagerOptimizerCommand;
|
||||
import me.xginko.villageroptimizer.config.Config;
|
||||
import me.xginko.villageroptimizer.config.LanguageCache;
|
||||
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
@ -15,14 +16,12 @@ import org.bstats.bukkit.Metrics;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@ -30,80 +29,99 @@ import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
public final class VillagerOptimizer extends JavaPlugin {
|
||||
public static final Style plugin_style = Style.style(TextColor.color(102,255,230), TextDecoration.BOLD);
|
||||
public static final Style STYLE = Style.style(TextColor.color(102,255,230), TextDecoration.BOLD);
|
||||
|
||||
private static VillagerOptimizer instance;
|
||||
private static VillagerCache villagerCache;
|
||||
private static FoliaLib foliaLib;
|
||||
private static HashMap<String, LanguageCache> languageCacheMap;
|
||||
private static Map<String, LanguageCache> languageCacheMap;
|
||||
private static Config config;
|
||||
private static BukkitAudiences audiences;
|
||||
private static ComponentLogger logger;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
logger = ComponentLogger.logger(this.getName());
|
||||
foliaLib = new FoliaLib(this);
|
||||
audiences = BukkitAudiences.create(this);
|
||||
logger = ComponentLogger.logger(this.getName());
|
||||
|
||||
logger.info(Component.text("╭────────────────────────────────────────────────────────────╮").style(plugin_style));
|
||||
logger.info(Component.text("│ │").style(plugin_style));
|
||||
logger.info(Component.text("│ │").style(plugin_style));
|
||||
logger.info(Component.text("│ _ __ _ __ __ │").style(plugin_style));
|
||||
logger.info(Component.text("│ | | / /(_)/ // /___ _ ___ _ ___ ____ │").style(plugin_style));
|
||||
logger.info(Component.text("│ | |/ // // // // _ `// _ `// -_)/ __/ │").style(plugin_style));
|
||||
logger.info(Component.text("│ |___//_//_//_/ \\_,_/ \\_, / \\__//_/ │").style(plugin_style));
|
||||
logger.info(Component.text("│ ____ __ _ /___/_ │").style(plugin_style));
|
||||
logger.info(Component.text("│ / __ \\ ___ / /_ (_)__ _ (_)___ ___ ____ │").style(plugin_style));
|
||||
logger.info(Component.text("│ / /_/ // _ \\/ __// // ' \\ / //_ // -_)/ __/ │").style(plugin_style));
|
||||
logger.info(Component.text("│ \\____// .__/\\__//_//_/_/_//_/ /__/\\__//_/ │").style(plugin_style));
|
||||
logger.info(Component.text("│ /_/ by xGinko │").style(plugin_style));
|
||||
logger.info(Component.text("│ │").style(plugin_style));
|
||||
logger.info(Component.text("│ │").style(plugin_style));
|
||||
logger.info(Component.text("╭────────────────────────────────────────────────────────────╮").style(STYLE));
|
||||
logger.info(Component.text("│ │").style(STYLE));
|
||||
logger.info(Component.text("│ │").style(STYLE));
|
||||
logger.info(Component.text("│ _ __ _ __ __ │").style(STYLE));
|
||||
logger.info(Component.text("│ | | / /(_)/ // /___ _ ___ _ ___ ____ │").style(STYLE));
|
||||
logger.info(Component.text("│ | |/ // // // // _ `// _ `// -_)/ __/ │").style(STYLE));
|
||||
logger.info(Component.text("│ |___//_//_//_/ \\_,_/ \\_, / \\__//_/ │").style(STYLE));
|
||||
logger.info(Component.text("│ ____ __ _ /___/_ │").style(STYLE));
|
||||
logger.info(Component.text("│ / __ \\ ___ / /_ (_)__ _ (_)___ ___ ____ │").style(STYLE));
|
||||
logger.info(Component.text("│ / /_/ // _ \\/ __// // ' \\ / //_ // -_)/ __/ │").style(STYLE));
|
||||
logger.info(Component.text("│ \\____// .__/\\__//_//_/_/_//_/ /__/\\__//_/ │").style(STYLE));
|
||||
logger.info(Component.text("│ /_/ by xGinko │").style(STYLE));
|
||||
logger.info(Component.text("│ │").style(STYLE));
|
||||
logger.info(Component.text("│ │").style(STYLE));
|
||||
logger.info(Component.text("│ ")
|
||||
.style(plugin_style).append(Component.text("https://github.com/xGinko/VillagerOptimizer")
|
||||
.color(NamedTextColor.GRAY)).append(Component.text(" │").style(plugin_style)));
|
||||
logger.info(Component.text("│ │").style(plugin_style));
|
||||
logger.info(Component.text("│ │").style(plugin_style));
|
||||
.style(STYLE).append(Component.text("https://github.com/xGinko/VillagerOptimizer")
|
||||
.color(NamedTextColor.GRAY)).append(Component.text(" │").style(STYLE)));
|
||||
logger.info(Component.text("│ │").style(STYLE));
|
||||
logger.info(Component.text("│ │").style(STYLE));
|
||||
logger.info(Component.text("│ ")
|
||||
.style(plugin_style).append(Component.text(" ➤ Loading Translations...").style(plugin_style))
|
||||
.append(Component.text(" │").style(plugin_style)));
|
||||
.style(STYLE).append(Component.text(" ➤ Loading Translations...").style(STYLE))
|
||||
.append(Component.text(" │").style(STYLE)));
|
||||
reloadLang(true);
|
||||
logger.info(Component.text("│ ")
|
||||
.style(plugin_style).append(Component.text(" ➤ Loading Config...").style(plugin_style))
|
||||
.append(Component.text(" │").style(plugin_style)));
|
||||
.style(STYLE).append(Component.text(" ➤ Loading Config...").style(STYLE))
|
||||
.append(Component.text(" │").style(STYLE)));
|
||||
reloadConfiguration();
|
||||
logger.info(Component.text("│ ")
|
||||
.style(plugin_style).append(Component.text(" ✓ Done.").color(NamedTextColor.WHITE).decorate(TextDecoration.BOLD))
|
||||
.append(Component.text(" │").style(plugin_style)));
|
||||
logger.info(Component.text("│ │").style(plugin_style));
|
||||
logger.info(Component.text("│ │").style(plugin_style));
|
||||
logger.info(Component.text("╰────────────────────────────────────────────────────────────╯").style(plugin_style));
|
||||
.style(STYLE).append(Component.text(" ✓ Done.").color(NamedTextColor.WHITE).decorate(TextDecoration.BOLD))
|
||||
.append(Component.text(" │").style(STYLE)));
|
||||
logger.info(Component.text("│ │").style(STYLE));
|
||||
logger.info(Component.text("│ │").style(STYLE));
|
||||
logger.info(Component.text("╰────────────────────────────────────────────────────────────╯").style(STYLE));
|
||||
|
||||
new Metrics(this, 19954);
|
||||
}
|
||||
|
||||
public static VillagerOptimizer getInstance() {
|
||||
@Override
|
||||
public void onDisable() {
|
||||
VillagerOptimizerModule.modules.forEach(VillagerOptimizerModule::disable);
|
||||
VillagerOptimizerModule.modules.clear();
|
||||
if (villagerCache != null) {
|
||||
villagerCache.cacheMap().clear();
|
||||
villagerCache = null;
|
||||
}
|
||||
if (audiences != null) {
|
||||
audiences.close();
|
||||
audiences = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static @NotNull VillagerOptimizer getInstance() {
|
||||
return instance;
|
||||
}
|
||||
public static Config getConfiguration() {
|
||||
public static @NotNull Config getConfiguration() {
|
||||
return config;
|
||||
}
|
||||
public static VillagerCache getCache() {
|
||||
public static @NotNull VillagerCache getCache() {
|
||||
return villagerCache;
|
||||
}
|
||||
public static FoliaLib getFoliaLib() {
|
||||
public static @NotNull FoliaLib getFoliaLib() {
|
||||
return foliaLib;
|
||||
}
|
||||
public static ComponentLogger getLog() {
|
||||
public static @NotNull ComponentLogger getLog() {
|
||||
return logger;
|
||||
}
|
||||
public static LanguageCache getLang(Locale locale) {
|
||||
public static @NotNull BukkitAudiences getAudiences() {
|
||||
return audiences;
|
||||
}
|
||||
public static @NotNull LanguageCache getLang(Locale locale) {
|
||||
return getLang(locale.toString().toLowerCase());
|
||||
}
|
||||
public static LanguageCache getLang(CommandSender commandSender) {
|
||||
return commandSender instanceof Player player ? getLang(player.locale()) : getLang(config.default_lang);
|
||||
public static @NotNull LanguageCache getLang(CommandSender commandSender) {
|
||||
return commandSender instanceof Player ? getLang(((Player) commandSender).locale()) : getLang(config.default_lang);
|
||||
}
|
||||
public static LanguageCache getLang(String lang) {
|
||||
public static @NotNull LanguageCache getLang(String lang) {
|
||||
if (!config.auto_lang) return languageCacheMap.get(config.default_lang.toString().toLowerCase());
|
||||
return languageCacheMap.getOrDefault(lang.replace("-", "_"), languageCacheMap.get(config.default_lang.toString().toLowerCase()));
|
||||
}
|
||||
@ -120,9 +138,8 @@ public final class VillagerOptimizer extends JavaPlugin {
|
||||
VillagerOptimizerCommand.reloadCommands();
|
||||
VillagerOptimizerModule.reloadModules();
|
||||
config.saveConfig();
|
||||
} catch (Exception e) {
|
||||
logger.error("Error loading config! - " + e.getLocalizedMessage());
|
||||
e.printStackTrace();
|
||||
} catch (Exception exception) {
|
||||
logger.error("Error loading config!", exception);
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,9 +151,9 @@ public final class VillagerOptimizer extends JavaPlugin {
|
||||
for (String fileName : getDefaultLanguageFiles()) {
|
||||
final String localeString = fileName.substring(fileName.lastIndexOf(File.separator) + 1, fileName.lastIndexOf('.'));
|
||||
if (startup) logger.info(
|
||||
Component.text("│ ").style(plugin_style)
|
||||
Component.text("│ ").style(STYLE)
|
||||
.append(Component.text(" "+localeString).color(NamedTextColor.WHITE).decorate(TextDecoration.BOLD))
|
||||
.append(Component.text(" │").style(plugin_style)));
|
||||
.append(Component.text(" │").style(STYLE)));
|
||||
else logger.info(String.format("Found language file for %s", localeString));
|
||||
languageCacheMap.put(localeString, new LanguageCache(localeString));
|
||||
}
|
||||
@ -147,9 +164,9 @@ public final class VillagerOptimizer extends JavaPlugin {
|
||||
String localeString = langMatcher.group(1).toLowerCase();
|
||||
if (!languageCacheMap.containsKey(localeString)) { // make sure it wasn't a default file that we already loaded
|
||||
if (startup) logger.info(
|
||||
Component.text("│ ").style(plugin_style)
|
||||
Component.text("│ ").style(STYLE)
|
||||
.append(Component.text(" "+localeString).color(NamedTextColor.WHITE).decorate(TextDecoration.BOLD))
|
||||
.append(Component.text(" │").style(plugin_style)));
|
||||
.append(Component.text(" │").style(STYLE)));
|
||||
else logger.info(String.format("Found language file for %s", localeString));
|
||||
languageCacheMap.put(localeString, new LanguageCache(localeString));
|
||||
}
|
||||
@ -157,22 +174,21 @@ public final class VillagerOptimizer extends JavaPlugin {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (startup) logger.error(
|
||||
Component.text("│ ").style(plugin_style)
|
||||
Component.text("│ ").style(STYLE)
|
||||
.append(Component.text("LANG ERROR").color(NamedTextColor.RED).decorate(TextDecoration.BOLD))
|
||||
.append(Component.text(" │").style(plugin_style)));
|
||||
else logger.error("Error loading language files! Language files will not reload to avoid errors, make sure to correct this before restarting the server!");
|
||||
e.printStackTrace();
|
||||
.append(Component.text(" │").style(STYLE)), e);
|
||||
else logger.error("Error loading language files! Language files will not reload to avoid errors, make sure to correct this before restarting the server!", e);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> getDefaultLanguageFiles() {
|
||||
private @NotNull Set<String> getDefaultLanguageFiles() {
|
||||
try (final JarFile pluginJarFile = new JarFile(this.getFile())) {
|
||||
return pluginJarFile.stream()
|
||||
.map(ZipEntry::getName)
|
||||
.filter(name -> name.startsWith("lang" + File.separator) && name.endsWith(".yml"))
|
||||
.collect(Collectors.toSet());
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed getting default lang files! - "+e.getLocalizedMessage());
|
||||
} catch (IOException ioException) {
|
||||
logger.error("Failed getting default lang files!", ioException);
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
@ -59,13 +59,14 @@ public final class WrappedVillager {
|
||||
/**
|
||||
* @return True if the villager is optimized by the supported plugin, otherwise false.
|
||||
*/
|
||||
public boolean isOptimized(Keyring.Spaces namespaces) {
|
||||
return switch (namespaces) {
|
||||
case VillagerOptimizer -> dataContainer.has(Keyring.VillagerOptimizer.OPTIMIZATION_TYPE.getKey(), PersistentDataType.STRING);
|
||||
case AntiVillagerLag -> dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_ANY.getKey(), PersistentDataType.STRING)
|
||||
|| dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_WORKSTATION.getKey(), PersistentDataType.STRING)
|
||||
|| dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_BLOCK.getKey(), PersistentDataType.STRING);
|
||||
};
|
||||
public boolean isOptimized(Keyring.Spaces namespace) {
|
||||
if (namespace == Keyring.Spaces.VillagerOptimizer) {
|
||||
return dataContainer.has(Keyring.VillagerOptimizer.OPTIMIZATION_TYPE.getKey(), PersistentDataType.STRING);
|
||||
} else {
|
||||
return dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_ANY.getKey(), PersistentDataType.STRING)
|
||||
|| dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_WORKSTATION.getKey(), PersistentDataType.STRING)
|
||||
|| dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_BLOCK.getKey(), PersistentDataType.STRING);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -92,26 +93,23 @@ public final class WrappedVillager {
|
||||
// Keep repeating task until villager is no longer trading with a player
|
||||
if (villager.isTrading()) return;
|
||||
|
||||
switch (type) {
|
||||
case NAMETAG, COMMAND, BLOCK, WORKSTATION -> {
|
||||
dataContainer.set(Keyring.VillagerOptimizer.OPTIMIZATION_TYPE.getKey(), PersistentDataType.STRING, type.name());
|
||||
villager.setAware(false);
|
||||
if (type == OptimizationType.NONE) {
|
||||
if (isOptimized(Keyring.Spaces.VillagerOptimizer)) {
|
||||
dataContainer.remove(Keyring.VillagerOptimizer.OPTIMIZATION_TYPE.getKey());
|
||||
}
|
||||
case NONE -> {
|
||||
if (isOptimized(Keyring.Spaces.VillagerOptimizer)) {
|
||||
dataContainer.remove(Keyring.VillagerOptimizer.OPTIMIZATION_TYPE.getKey());
|
||||
}
|
||||
if (parseOther) {
|
||||
if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_ANY.getKey(), PersistentDataType.STRING))
|
||||
dataContainer.remove(Keyring.AntiVillagerLag.OPTIMIZED_ANY.getKey());
|
||||
if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_WORKSTATION.getKey(), PersistentDataType.STRING))
|
||||
dataContainer.remove(Keyring.AntiVillagerLag.OPTIMIZED_WORKSTATION.getKey());
|
||||
if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_BLOCK.getKey(), PersistentDataType.STRING))
|
||||
dataContainer.remove(Keyring.AntiVillagerLag.OPTIMIZED_BLOCK.getKey());
|
||||
}
|
||||
villager.setAware(true);
|
||||
villager.setAI(true);
|
||||
if (parseOther) {
|
||||
if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_ANY.getKey(), PersistentDataType.STRING))
|
||||
dataContainer.remove(Keyring.AntiVillagerLag.OPTIMIZED_ANY.getKey());
|
||||
if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_WORKSTATION.getKey(), PersistentDataType.STRING))
|
||||
dataContainer.remove(Keyring.AntiVillagerLag.OPTIMIZED_WORKSTATION.getKey());
|
||||
if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_BLOCK.getKey(), PersistentDataType.STRING))
|
||||
dataContainer.remove(Keyring.AntiVillagerLag.OPTIMIZED_BLOCK.getKey());
|
||||
}
|
||||
villager.setAware(true);
|
||||
villager.setAI(true);
|
||||
} else {
|
||||
dataContainer.set(Keyring.VillagerOptimizer.OPTIMIZATION_TYPE.getKey(), PersistentDataType.STRING, type.name());
|
||||
villager.setAware(false);
|
||||
}
|
||||
|
||||
// End repeating task once logic is finished
|
||||
@ -134,26 +132,26 @@ public final class WrappedVillager {
|
||||
}
|
||||
|
||||
public @NotNull OptimizationType getOptimizationType(Keyring.Spaces namespaces) {
|
||||
return switch (namespaces) {
|
||||
case VillagerOptimizer -> {
|
||||
if (isOptimized(Keyring.Spaces.VillagerOptimizer)) {
|
||||
yield OptimizationType.valueOf(dataContainer.get(Keyring.VillagerOptimizer.OPTIMIZATION_TYPE.getKey(), PersistentDataType.STRING));
|
||||
}
|
||||
yield OptimizationType.NONE;
|
||||
if (namespaces == Keyring.Spaces.VillagerOptimizer) {
|
||||
if (!isOptimized(Keyring.Spaces.VillagerOptimizer)) {
|
||||
return OptimizationType.valueOf(dataContainer.get(Keyring.VillagerOptimizer.OPTIMIZATION_TYPE.getKey(), PersistentDataType.STRING));
|
||||
} else {
|
||||
return OptimizationType.NONE;
|
||||
}
|
||||
case AntiVillagerLag -> {
|
||||
if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_BLOCK.getKey(), PersistentDataType.STRING)) {
|
||||
yield OptimizationType.BLOCK;
|
||||
}
|
||||
if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_WORKSTATION.getKey(), PersistentDataType.STRING)) {
|
||||
yield OptimizationType.WORKSTATION;
|
||||
}
|
||||
if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_ANY.getKey(), PersistentDataType.STRING)) {
|
||||
yield OptimizationType.COMMAND; // Best we can do
|
||||
}
|
||||
yield OptimizationType.NONE;
|
||||
}
|
||||
if (namespaces == Keyring.Spaces.AntiVillagerLag) {
|
||||
if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_BLOCK.getKey(), PersistentDataType.STRING)) {
|
||||
return OptimizationType.BLOCK;
|
||||
}
|
||||
};
|
||||
if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_WORKSTATION.getKey(), PersistentDataType.STRING)) {
|
||||
return OptimizationType.WORKSTATION;
|
||||
}
|
||||
if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_ANY.getKey(), PersistentDataType.STRING)) {
|
||||
return OptimizationType.COMMAND; // Best we can do
|
||||
}
|
||||
return OptimizationType.NONE;
|
||||
}
|
||||
return OptimizationType.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,6 +8,7 @@ import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@ -17,7 +18,7 @@ public interface VillagerOptimizerCommand extends CommandExecutor, TabCompleter
|
||||
String label();
|
||||
|
||||
List<String> NO_TABCOMPLETES = Collections.emptyList();
|
||||
List<String> RADIUS_TABCOMPLETES = List.of("5", "10", "25", "50");
|
||||
List<String> RADIUS_TABCOMPLETES = Arrays.asList("5", "10", "25", "50");
|
||||
|
||||
HashSet<VillagerOptimizerCommand> commands = new HashSet<>();
|
||||
|
||||
|
@ -9,6 +9,7 @@ import me.xginko.villageroptimizer.enums.OptimizationType;
|
||||
import me.xginko.villageroptimizer.enums.permissions.Bypass;
|
||||
import me.xginko.villageroptimizer.enums.permissions.Commands;
|
||||
import me.xginko.villageroptimizer.events.VillagerOptimizeEvent;
|
||||
import me.xginko.villageroptimizer.utils.KyoriUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextReplacementConfig;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
@ -32,9 +33,9 @@ public class OptVillagersRadius implements VillagerOptimizerCommand {
|
||||
public OptVillagersRadius() {
|
||||
Config config = VillagerOptimizer.getConfiguration();
|
||||
this.max_radius = config.getInt("optimization-methods.commands.optimizevillagers.max-block-radius", 100);
|
||||
this.cooldown = config.getInt("optimization-methods.commands.optimizevillagers.cooldown-seconds", 600, """
|
||||
Cooldown in seconds until a villager can be optimized again using the command.\s
|
||||
Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior.""") * 1000L;
|
||||
this.cooldown = config.getInt("optimization-methods.commands.optimizevillagers.cooldown-seconds", 600,
|
||||
"Cooldown in seconds until a villager can be optimized again using the command.\n" +
|
||||
"Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior.") * 1000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -50,18 +51,21 @@ public class OptVillagersRadius implements VillagerOptimizerCommand {
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
|
||||
if (!sender.hasPermission(Commands.OPTIMIZE_RADIUS.get())) {
|
||||
sender.sendMessage(VillagerOptimizer.getLang(sender).no_permission);
|
||||
KyoriUtil.sendMessage(sender, VillagerOptimizer.getLang(sender).no_permission);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(Component.text("This command can only be executed by a player.")
|
||||
if (!(sender instanceof Player)) {
|
||||
KyoriUtil.sendMessage(sender, Component.text("This command can only be executed by a player.")
|
||||
.color(NamedTextColor.RED).decorate(TextDecoration.BOLD));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
|
||||
if (args.length != 1) {
|
||||
VillagerOptimizer.getLang(player.locale()).command_specify_radius.forEach(player::sendMessage);
|
||||
VillagerOptimizer.getLang(player.locale()).command_specify_radius
|
||||
.forEach(line -> KyoriUtil.sendMessage(sender, line));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -71,7 +75,8 @@ public class OptVillagersRadius implements VillagerOptimizerCommand {
|
||||
final int safeRadius = (int) Math.sqrt(specifiedRadius * specifiedRadius);
|
||||
|
||||
if (safeRadius == 0) {
|
||||
VillagerOptimizer.getLang(player.locale()).command_radius_invalid.forEach(player::sendMessage);
|
||||
VillagerOptimizer.getLang(player.locale()).command_radius_invalid
|
||||
.forEach(line -> KyoriUtil.sendMessage(sender, line));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -80,7 +85,8 @@ public class OptVillagersRadius implements VillagerOptimizerCommand {
|
||||
.matchLiteral("%distance%")
|
||||
.replacement(Integer.toString(max_radius))
|
||||
.build();
|
||||
VillagerOptimizer.getLang(player.locale()).command_radius_limit_exceed.forEach(line -> player.sendMessage(line.replaceText(limit)));
|
||||
VillagerOptimizer.getLang(player.locale()).command_radius_limit_exceed
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(limit)));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -114,7 +120,8 @@ public class OptVillagersRadius implements VillagerOptimizerCommand {
|
||||
.matchLiteral("%radius%")
|
||||
.replacement(Integer.toString(safeRadius))
|
||||
.build();
|
||||
VillagerOptimizer.getLang(player.locale()).command_no_villagers_nearby.forEach(line -> player.sendMessage(line.replaceText(radius)));
|
||||
VillagerOptimizer.getLang(player.locale()).command_no_villagers_nearby
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(radius)));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -127,20 +134,20 @@ public class OptVillagersRadius implements VillagerOptimizerCommand {
|
||||
.matchLiteral("%radius%")
|
||||
.replacement(Integer.toString(safeRadius))
|
||||
.build();
|
||||
VillagerOptimizer.getLang(player.locale()).command_optimize_success.forEach(line -> player.sendMessage(line
|
||||
.replaceText(success_amount)
|
||||
.replaceText(radius)
|
||||
));
|
||||
VillagerOptimizer.getLang(player.locale()).command_optimize_success
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(success_amount).replaceText(radius)));
|
||||
}
|
||||
if (failCount > 0) {
|
||||
final TextReplacementConfig alreadyOptimized = TextReplacementConfig.builder()
|
||||
.matchLiteral("%amount%")
|
||||
.replacement(Integer.toString(failCount))
|
||||
.build();
|
||||
VillagerOptimizer.getLang(player.locale()).command_optimize_fail.forEach(line -> player.sendMessage(line.replaceText(alreadyOptimized)));
|
||||
VillagerOptimizer.getLang(player.locale()).command_optimize_fail
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(alreadyOptimized)));
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
VillagerOptimizer.getLang(player.locale()).command_radius_invalid.forEach(player::sendMessage);
|
||||
VillagerOptimizer.getLang(player.locale()).command_radius_invalid
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -7,6 +7,7 @@ import me.xginko.villageroptimizer.commands.VillagerOptimizerCommand;
|
||||
import me.xginko.villageroptimizer.enums.OptimizationType;
|
||||
import me.xginko.villageroptimizer.enums.permissions.Commands;
|
||||
import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent;
|
||||
import me.xginko.villageroptimizer.utils.KyoriUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextReplacementConfig;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
@ -27,7 +28,8 @@ public class UnOptVillagersRadius implements VillagerOptimizerCommand {
|
||||
private final int max_radius;
|
||||
|
||||
public UnOptVillagersRadius() {
|
||||
this.max_radius = VillagerOptimizer.getConfiguration().getInt("optimization-methods.commands.unoptimizevillagers.max-block-radius", 100);
|
||||
this.max_radius = VillagerOptimizer.getConfiguration()
|
||||
.getInt("optimization-methods.commands.unoptimizevillagers.max-block-radius", 100);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -43,18 +45,21 @@ public class UnOptVillagersRadius implements VillagerOptimizerCommand {
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
|
||||
if (!sender.hasPermission(Commands.UNOPTIMIZE_RADIUS.get())) {
|
||||
sender.sendMessage(VillagerOptimizer.getLang(sender).no_permission);
|
||||
KyoriUtil.sendMessage(sender, VillagerOptimizer.getLang(sender).no_permission);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(Component.text("This command can only be executed by a player.")
|
||||
if (!(sender instanceof Player)) {
|
||||
KyoriUtil.sendMessage(sender, Component.text("This command can only be executed by a player.")
|
||||
.color(NamedTextColor.RED).decorate(TextDecoration.BOLD));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
|
||||
if (args.length != 1) {
|
||||
VillagerOptimizer.getLang(player.locale()).command_specify_radius.forEach(player::sendMessage);
|
||||
VillagerOptimizer.getLang(player.locale()).command_specify_radius
|
||||
.forEach(line -> KyoriUtil.sendMessage(sender, line));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -64,7 +69,8 @@ public class UnOptVillagersRadius implements VillagerOptimizerCommand {
|
||||
final int safeRadius = (int) Math.sqrt(specifiedRadius * specifiedRadius);
|
||||
|
||||
if (safeRadius == 0) {
|
||||
VillagerOptimizer.getLang(player.locale()).command_radius_invalid.forEach(player::sendMessage);
|
||||
VillagerOptimizer.getLang(player.locale()).command_radius_invalid
|
||||
.forEach(line -> KyoriUtil.sendMessage(sender, line));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -73,7 +79,8 @@ public class UnOptVillagersRadius implements VillagerOptimizerCommand {
|
||||
.matchLiteral("%distance%")
|
||||
.replacement(Integer.toString(max_radius))
|
||||
.build();
|
||||
VillagerOptimizer.getLang(player.locale()).command_radius_limit_exceed.forEach(line -> player.sendMessage(line.replaceText(limit)));
|
||||
VillagerOptimizer.getLang(player.locale()).command_radius_limit_exceed
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(limit)));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -102,7 +109,8 @@ public class UnOptVillagersRadius implements VillagerOptimizerCommand {
|
||||
.matchLiteral("%radius%")
|
||||
.replacement(Integer.toString(safeRadius))
|
||||
.build();
|
||||
VillagerOptimizer.getLang(player.locale()).command_no_villagers_nearby.forEach(line -> player.sendMessage(line.replaceText(radius)));
|
||||
VillagerOptimizer.getLang(player.locale()).command_no_villagers_nearby
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(radius)));
|
||||
} else {
|
||||
final TextReplacementConfig success_amount = TextReplacementConfig.builder()
|
||||
.matchLiteral("%amount%")
|
||||
@ -112,13 +120,12 @@ public class UnOptVillagersRadius implements VillagerOptimizerCommand {
|
||||
.matchLiteral("%radius%")
|
||||
.replacement(Integer.toString(safeRadius))
|
||||
.build();
|
||||
VillagerOptimizer.getLang(player.locale()).command_unoptimize_success.forEach(line -> player.sendMessage(line
|
||||
.replaceText(success_amount)
|
||||
.replaceText(radius)
|
||||
));
|
||||
VillagerOptimizer.getLang(player.locale()).command_unoptimize_success
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(success_amount).replaceText(radius)));
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
VillagerOptimizer.getLang(player.locale()).command_radius_invalid.forEach(player::sendMessage);
|
||||
VillagerOptimizer.getLang(player.locale()).command_radius_invalid
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -7,13 +7,16 @@ import me.xginko.villageroptimizer.commands.villageroptimizer.subcommands.Disabl
|
||||
import me.xginko.villageroptimizer.commands.villageroptimizer.subcommands.ReloadSubCmd;
|
||||
import me.xginko.villageroptimizer.commands.villageroptimizer.subcommands.VersionSubCmd;
|
||||
import me.xginko.villageroptimizer.enums.permissions.Commands;
|
||||
import me.xginko.villageroptimizer.utils.KyoriUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class VillagerOptimizerCmd implements VillagerOptimizerCommand {
|
||||
|
||||
@ -21,8 +24,8 @@ public class VillagerOptimizerCmd implements VillagerOptimizerCommand {
|
||||
private final List<String> tabCompleter;
|
||||
|
||||
public VillagerOptimizerCmd() {
|
||||
subCommands = List.of(new ReloadSubCmd(), new VersionSubCmd(), new DisableSubCmd());
|
||||
tabCompleter = subCommands.stream().map(SubCommand::getLabel).toList();
|
||||
subCommands = Arrays.asList(new ReloadSubCmd(), new VersionSubCmd(), new DisableSubCmd());
|
||||
tabCompleter = subCommands.stream().map(SubCommand::getLabel).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -55,21 +58,21 @@ public class VillagerOptimizerCmd implements VillagerOptimizerCommand {
|
||||
|
||||
private void sendCommandOverview(CommandSender sender) {
|
||||
if (!sender.hasPermission(Commands.RELOAD.get()) && !sender.hasPermission(Commands.VERSION.get())) return;
|
||||
sender.sendMessage(Component.text("-----------------------------------------------------").color(NamedTextColor.GRAY));
|
||||
sender.sendMessage(Component.text("VillagerOptimizer Commands").color(VillagerOptimizer.plugin_style.color()));
|
||||
sender.sendMessage(Component.text("-----------------------------------------------------").color(NamedTextColor.GRAY));
|
||||
subCommands.forEach(subCommand -> sender.sendMessage(
|
||||
KyoriUtil.sendMessage(sender, Component.text("-----------------------------------------------------").color(NamedTextColor.GRAY));
|
||||
KyoriUtil.sendMessage(sender, Component.text("VillagerOptimizer Commands").color(VillagerOptimizer.STYLE.color()));
|
||||
KyoriUtil.sendMessage(sender, Component.text("-----------------------------------------------------").color(NamedTextColor.GRAY));
|
||||
subCommands.forEach(subCommand -> KyoriUtil.sendMessage(sender,
|
||||
subCommand.getSyntax().append(Component.text(" - ").color(NamedTextColor.DARK_GRAY)).append(subCommand.getDescription())));
|
||||
sender.sendMessage(
|
||||
Component.text("/optimizevillagers <blockradius>").color(VillagerOptimizer.plugin_style.color())
|
||||
KyoriUtil.sendMessage(sender,
|
||||
Component.text("/optimizevillagers <blockradius>").color(VillagerOptimizer.STYLE.color())
|
||||
.append(Component.text(" - ").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text("Optimize villagers in a radius").color(NamedTextColor.GRAY))
|
||||
);
|
||||
sender.sendMessage(
|
||||
Component.text("/unoptmizevillagers <blockradius>").color(VillagerOptimizer.plugin_style.color())
|
||||
KyoriUtil.sendMessage(sender,
|
||||
Component.text("/unoptmizevillagers <blockradius>").color(VillagerOptimizer.STYLE.color())
|
||||
.append(Component.text(" - ").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text("Unoptimize villagers in a radius").color(NamedTextColor.GRAY))
|
||||
);
|
||||
sender.sendMessage(Component.text("-----------------------------------------------------").color(NamedTextColor.GRAY));
|
||||
KyoriUtil.sendMessage(sender, Component.text("-----------------------------------------------------").color(NamedTextColor.GRAY));
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import me.xginko.villageroptimizer.VillagerOptimizer;
|
||||
import me.xginko.villageroptimizer.commands.SubCommand;
|
||||
import me.xginko.villageroptimizer.enums.permissions.Commands;
|
||||
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
|
||||
import me.xginko.villageroptimizer.utils.KyoriUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
@ -23,21 +24,21 @@ public class DisableSubCmd extends SubCommand {
|
||||
|
||||
@Override
|
||||
public TextComponent getSyntax() {
|
||||
return Component.text("/villageroptimizer disable").color(VillagerOptimizer.plugin_style.color());
|
||||
return Component.text("/villageroptimizer disable").color(VillagerOptimizer.STYLE.color());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform(CommandSender sender, String[] args) {
|
||||
if (!sender.hasPermission(Commands.DISABLE.get())) {
|
||||
sender.sendMessage(VillagerOptimizer.getLang(sender).no_permission);
|
||||
KyoriUtil.sendMessage(sender, VillagerOptimizer.getLang(sender).no_permission);
|
||||
return;
|
||||
}
|
||||
|
||||
sender.sendMessage(Component.text("Disabling VillagerOptimizer...").color(NamedTextColor.RED));
|
||||
KyoriUtil.sendMessage(sender, Component.text("Disabling VillagerOptimizer...").color(NamedTextColor.RED));
|
||||
VillagerOptimizerModule.modules.forEach(VillagerOptimizerModule::disable);
|
||||
VillagerOptimizerModule.modules.clear();
|
||||
VillagerOptimizer.getCache().cacheMap().clear();
|
||||
sender.sendMessage(Component.text("Disabled all plugin listeners and tasks.").color(NamedTextColor.GREEN));
|
||||
sender.sendMessage(Component.text("You can enable the plugin again using the reload command.").color(NamedTextColor.YELLOW));
|
||||
KyoriUtil.sendMessage(sender, Component.text("Disabled all plugin listeners and tasks.").color(NamedTextColor.GREEN));
|
||||
KyoriUtil.sendMessage(sender, Component.text("You can enable the plugin again using the reload command.").color(NamedTextColor.YELLOW));
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package me.xginko.villageroptimizer.commands.villageroptimizer.subcommands;
|
||||
import me.xginko.villageroptimizer.VillagerOptimizer;
|
||||
import me.xginko.villageroptimizer.commands.SubCommand;
|
||||
import me.xginko.villageroptimizer.enums.permissions.Commands;
|
||||
import me.xginko.villageroptimizer.utils.KyoriUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
@ -22,20 +23,20 @@ public class ReloadSubCmd extends SubCommand {
|
||||
|
||||
@Override
|
||||
public TextComponent getSyntax() {
|
||||
return Component.text("/villageroptimizer reload").color(VillagerOptimizer.plugin_style.color());
|
||||
return Component.text("/villageroptimizer reload").color(VillagerOptimizer.STYLE.color());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform(CommandSender sender, String[] args) {
|
||||
if (!sender.hasPermission(Commands.RELOAD.get())) {
|
||||
sender.sendMessage(VillagerOptimizer.getLang(sender).no_permission);
|
||||
KyoriUtil.sendMessage(sender, VillagerOptimizer.getLang(sender).no_permission);
|
||||
return;
|
||||
}
|
||||
|
||||
sender.sendMessage(Component.text("Reloading VillagerOptimizer...").color(NamedTextColor.WHITE));
|
||||
KyoriUtil.sendMessage(sender, Component.text("Reloading VillagerOptimizer...").color(NamedTextColor.WHITE));
|
||||
VillagerOptimizer.getFoliaLib().getImpl().runNextTick(reload -> { // Reload in sync with the server
|
||||
VillagerOptimizer.getInstance().reloadPlugin();
|
||||
sender.sendMessage(Component.text("Reload complete.").color(NamedTextColor.GREEN));
|
||||
KyoriUtil.sendMessage(sender, Component.text("Reload complete.").color(NamedTextColor.GREEN));
|
||||
});
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import io.papermc.paper.plugin.configuration.PluginMeta;
|
||||
import me.xginko.villageroptimizer.VillagerOptimizer;
|
||||
import me.xginko.villageroptimizer.commands.SubCommand;
|
||||
import me.xginko.villageroptimizer.enums.permissions.Commands;
|
||||
import me.xginko.villageroptimizer.utils.KyoriUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
@ -25,14 +26,14 @@ public class VersionSubCmd extends SubCommand {
|
||||
|
||||
@Override
|
||||
public TextComponent getSyntax() {
|
||||
return Component.text("/villageroptimizer version").color(VillagerOptimizer.plugin_style.color());
|
||||
return Component.text("/villageroptimizer version").color(VillagerOptimizer.STYLE.color());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"deprecation", "UnstableApiUsage"})
|
||||
public void perform(CommandSender sender, String[] args) {
|
||||
if (!sender.hasPermission(Commands.VERSION.get())) {
|
||||
sender.sendMessage(VillagerOptimizer.getLang(sender).no_permission);
|
||||
KyoriUtil.sendMessage(sender, VillagerOptimizer.getLang(sender).no_permission);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -52,10 +53,10 @@ public class VersionSubCmd extends SubCommand {
|
||||
author = pluginYML.getAuthors().get(0);
|
||||
}
|
||||
|
||||
sender.sendMessage(Component.newline()
|
||||
KyoriUtil.sendMessage(sender, Component.newline()
|
||||
.append(
|
||||
Component.text(name + " " + version)
|
||||
.style(VillagerOptimizer.plugin_style)
|
||||
.style(VillagerOptimizer.STYLE)
|
||||
.clickEvent(ClickEvent.openUrl(website))
|
||||
)
|
||||
.append(Component.text(" by ").color(NamedTextColor.GRAY))
|
||||
|
@ -33,16 +33,16 @@ public class Config {
|
||||
"If set to true, will display messages based on client language");
|
||||
this.cache_keep_time_seconds = getInt("general.cache-keep-time-seconds", 30,
|
||||
"The amount of time in seconds a villager will be kept in the plugin's cache.");
|
||||
this.support_other_plugins = getBoolean("general.support-avl-villagers", false, """
|
||||
Enable if you have previously used AntiVillagerLag (https://www.spigotmc.org/resources/antivillagerlag.102949/).\s
|
||||
Tries to read pre-existing info like optimization state so players don't need to reoptimize their villagers.""");
|
||||
this.support_other_plugins = getBoolean("general.support-avl-villagers", false,
|
||||
"Enable if you have previously used AntiVillagerLag (https://www.spigotmc.org/resources/antivillagerlag.102949/).\n" +
|
||||
"Tries to read pre-existing info like optimization state so players don't need to reoptimize their villagers.");
|
||||
}
|
||||
|
||||
public void saveConfig() {
|
||||
try {
|
||||
this.config.save();
|
||||
} catch (Exception e) {
|
||||
VillagerOptimizer.getLog().error("Failed to save config file! - " + e.getLocalizedMessage());
|
||||
} catch (Throwable throwable) {
|
||||
VillagerOptimizer.getLog().error("Failed to save config file!", throwable);
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,11 +51,10 @@ public class Config {
|
||||
this.createTitledSection("General", "general");
|
||||
this.createTitledSection("Optimization", "optimization-methods");
|
||||
this.config.addDefault("optimization-methods.commands.unoptimizevillagers", null);
|
||||
this.config.addComment("optimization-methods.commands", """
|
||||
If you want to disable commands, negate the following permissions:\s
|
||||
villageroptimizer.cmd.optimize\s
|
||||
villageroptimizer.cmd.unoptimize
|
||||
""");
|
||||
this.config.addComment("optimization-methods.commands",
|
||||
"If you want to disable commands, negate the following permissions:\n" +
|
||||
"villageroptimizer.cmd.optimize\n" +
|
||||
"villageroptimizer.cmd.unoptimize");
|
||||
this.config.addDefault("optimization-methods.nametag-optimization.enable", true);
|
||||
this.createTitledSection("Villager Chunk Limit", "villager-chunk-limit");
|
||||
this.createTitledSection("Gameplay", "gameplay");
|
||||
|
@ -7,7 +7,9 @@ import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class LanguageCache {
|
||||
|
||||
@ -28,62 +30,62 @@ public class LanguageCache {
|
||||
File parent = langYML.getParentFile();
|
||||
if (!parent.exists() && !parent.mkdir())
|
||||
VillagerOptimizer.getLog().error("Failed to create lang directory.");
|
||||
// Check if the file already exists and save the one from the plugins resources folder if it does not
|
||||
// Check if the file already exists and save the one from the plugin's resources folder if it does not
|
||||
if (!langYML.exists())
|
||||
plugin.saveResource("lang" + File.separator + locale + ".yml", false);
|
||||
// Finally load the lang file with configmaster
|
||||
// Finally, load the lang file with configmaster
|
||||
this.lang = ConfigFile.loadConfig(langYML);
|
||||
|
||||
// General
|
||||
this.no_permission = getTranslation("messages.no-permission",
|
||||
"<red>You don't have permission to use this command.");
|
||||
this.trades_restocked = getListTranslation("messages.trades-restocked",
|
||||
List.of("<green>All trades have been restocked! Next restock in %time%"));
|
||||
"<green>All trades have been restocked! Next restock in %time%");
|
||||
this.optimize_for_trading = getListTranslation("messages.optimize-to-trade",
|
||||
List.of("<red>You need to optimize this villager before you can trade with it."));
|
||||
"<red>You need to optimize this villager before you can trade with it.");
|
||||
this.villager_leveling_up = getListTranslation("messages.villager-leveling-up",
|
||||
List.of("<yellow>Villager is currently leveling up! You can use the villager again in %time%."));
|
||||
"<yellow>Villager is currently leveling up! You can use the villager again in %time%.");
|
||||
// Nametag
|
||||
this.nametag_optimize_success = getListTranslation("messages.nametag.optimize-success",
|
||||
List.of("<green>Successfully optimized villager by using a nametag."));
|
||||
"<green>Successfully optimized villager by using a nametag.");
|
||||
this.nametag_on_optimize_cooldown = getListTranslation("messages.nametag.optimize-on-cooldown",
|
||||
List.of("<gray>You need to wait %time% until you can optimize this villager again."));
|
||||
"<gray>You need to wait %time% until you can optimize this villager again.");
|
||||
this.nametag_unoptimize_success = getListTranslation("messages.nametag.unoptimize-success",
|
||||
List.of("<green>Successfully unoptimized villager by using a nametag."));
|
||||
"<green>Successfully unoptimized villager by using a nametag.");
|
||||
// Block
|
||||
this.block_optimize_success = getListTranslation("messages.block.optimize-success",
|
||||
List.of("<green>%villagertype% villager successfully optimized using block %blocktype%."));
|
||||
"<green>%villagertype% villager successfully optimized using block %blocktype%.");
|
||||
this.block_on_optimize_cooldown = getListTranslation("messages.block.optimize-on-cooldown",
|
||||
List.of("<gray>You need to wait %time% until you can optimize this villager again."));
|
||||
"<gray>You need to wait %time% until you can optimize this villager again.");
|
||||
this.block_unoptimize_success = getListTranslation("messages.block.unoptimize-success",
|
||||
List.of("<green>Successfully unoptimized %villagertype% villager by removing %blocktype%."));
|
||||
"<green>Successfully unoptimized %villagertype% villager by removing %blocktype%.");
|
||||
// Workstation
|
||||
this.workstation_optimize_success = getListTranslation("messages.workstation.optimize-success",
|
||||
List.of("<green>%villagertype% villager successfully optimized using workstation %workstation%."));
|
||||
"<green>%villagertype% villager successfully optimized using workstation %workstation%.");
|
||||
this.workstation_on_optimize_cooldown = getListTranslation("messages.workstation.optimize-on-cooldown",
|
||||
List.of("<gray>You need to wait %time% until you can optimize this villager again."));
|
||||
"<gray>You need to wait %time% until you can optimize this villager again.");
|
||||
this.workstation_unoptimize_success = getListTranslation("messages.workstation.unoptimize-success",
|
||||
List.of("<green>Successfully unoptimized %villagertype% villager by removing workstation block %workstation%."));
|
||||
"<green>Successfully unoptimized %villagertype% villager by removing workstation block %workstation%.");
|
||||
// Command
|
||||
this.command_optimize_success = getListTranslation("messages.command.optimize-success",
|
||||
List.of("<green>Successfully optimized %amount% villager(s) in a radius of %radius% blocks."));
|
||||
"<green>Successfully optimized %amount% villager(s) in a radius of %radius% blocks.");
|
||||
this.command_radius_limit_exceed = getListTranslation("messages.command.radius-limit-exceed",
|
||||
List.of("<red>The radius you entered exceeds the limit of %distance% blocks."));
|
||||
"<red>The radius you entered exceeds the limit of %distance% blocks.");
|
||||
this.command_optimize_fail = getListTranslation("messages.command.optimize-fail",
|
||||
List.of("<gray>%amount% villagers couldn't be optimized because they have recently been optimized."));
|
||||
"<gray>%amount% villagers couldn't be optimized because they have recently been optimized.");
|
||||
this.command_unoptimize_success = getListTranslation("messages.command.unoptimize-success",
|
||||
List.of("<green>Successfully unoptimized %amount% villager(s) in a radius of %radius% blocks."));
|
||||
"<green>Successfully unoptimized %amount% villager(s) in a radius of %radius% blocks.");
|
||||
this.command_specify_radius = getListTranslation("messages.command.specify-radius",
|
||||
List.of("<red>Please specify a radius."));
|
||||
"<red>Please specify a radius.");
|
||||
this.command_radius_invalid = getListTranslation("messages.command.radius-invalid",
|
||||
List.of("<red>The radius you entered is not a valid number. Try again."));
|
||||
"<red>The radius you entered is not a valid number. Try again.");
|
||||
this.command_no_villagers_nearby = getListTranslation("messages.command.no-villagers-nearby",
|
||||
List.of("<gray>Couldn't find any employed villagers within a radius of %radius%."));
|
||||
"<gray>Couldn't find any employed villagers within a radius of %radius%.");
|
||||
|
||||
try {
|
||||
this.lang.save();
|
||||
} catch (Exception e) {
|
||||
VillagerOptimizer.getLog().error("Failed to save language file: "+ langYML.getName() +" - " + e.getLocalizedMessage());
|
||||
} catch (Throwable throwable) {
|
||||
VillagerOptimizer.getLog().error("Failed to save language file: "+ langYML.getName(), throwable);
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,18 +94,8 @@ public class LanguageCache {
|
||||
return MiniMessage.miniMessage().deserialize(this.lang.getString(path, defaultTranslation));
|
||||
}
|
||||
|
||||
public @NotNull Component getTranslation(@NotNull String path, @NotNull String defaultTranslation, @NotNull String comment) {
|
||||
this.lang.addDefault(path, defaultTranslation, comment);
|
||||
return MiniMessage.miniMessage().deserialize(this.lang.getString(path, defaultTranslation));
|
||||
}
|
||||
|
||||
public @NotNull List<Component> getListTranslation(@NotNull String path, @NotNull List<String> defaultTranslation) {
|
||||
this.lang.addDefault(path, defaultTranslation);
|
||||
return this.lang.getStringList(path).stream().map(MiniMessage.miniMessage()::deserialize).toList();
|
||||
}
|
||||
|
||||
public @NotNull List<Component> getListTranslation(@NotNull String path, @NotNull List<String> defaultTranslation, @NotNull String comment) {
|
||||
this.lang.addDefault(path, defaultTranslation, comment);
|
||||
return this.lang.getStringList(path).stream().map(MiniMessage.miniMessage()::deserialize).toList();
|
||||
public @NotNull List<Component> getListTranslation(@NotNull String path, @NotNull String... defaultTranslation) {
|
||||
this.lang.addDefault(path, Arrays.asList(defaultTranslation));
|
||||
return this.lang.getStringList(path).stream().map(MiniMessage.miniMessage()::deserialize).collect(Collectors.toList());
|
||||
}
|
||||
}
|
@ -43,7 +43,6 @@ public class Keyring {
|
||||
* @return a {@link NamespacedKey} that can be used to test for and read data stored by plugins
|
||||
* from a {@link PersistentDataContainer}
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public static NamespacedKey getKey(@NotNull String pluginName, @NotNull String key) {
|
||||
return new NamespacedKey(pluginName.toLowerCase(Locale.ROOT), key);
|
||||
}
|
||||
@ -58,7 +57,6 @@ public class Keyring {
|
||||
|
||||
private final @NotNull NamespacedKey key;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
VillagerOptimizer(@NotNull String key) {
|
||||
this.key = new NamespacedKey(Spaces.VillagerOptimizer.namespace(), key);
|
||||
}
|
||||
@ -80,7 +78,6 @@ public class Keyring {
|
||||
|
||||
private final @NotNull NamespacedKey key;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
AntiVillagerLag(@NotNull String avlKey) {
|
||||
this.key = new NamespacedKey(Spaces.AntiVillagerLag.namespace(), avlKey);
|
||||
}
|
||||
|
@ -17,7 +17,12 @@ public class VillagerOptimizeEvent extends Event implements Cancellable {
|
||||
private final @Nullable Player whoOptimised;
|
||||
private boolean isCancelled = false;
|
||||
|
||||
public VillagerOptimizeEvent(@NotNull WrappedVillager wrappedVillager, @NotNull OptimizationType optimizationType, @Nullable Player whoOptimised, boolean isAsync) throws IllegalArgumentException {
|
||||
public VillagerOptimizeEvent(
|
||||
@NotNull WrappedVillager wrappedVillager,
|
||||
@NotNull OptimizationType optimizationType,
|
||||
@Nullable Player whoOptimised,
|
||||
boolean isAsync
|
||||
) throws IllegalArgumentException {
|
||||
super(isAsync);
|
||||
this.wrappedVillager = wrappedVillager;
|
||||
this.whoOptimised = whoOptimised;
|
||||
@ -28,7 +33,11 @@ public class VillagerOptimizeEvent extends Event implements Cancellable {
|
||||
}
|
||||
}
|
||||
|
||||
public VillagerOptimizeEvent(@NotNull WrappedVillager wrappedVillager, @NotNull OptimizationType optimizationType, @Nullable Player whoOptimised) throws IllegalArgumentException {
|
||||
public VillagerOptimizeEvent(
|
||||
@NotNull WrappedVillager wrappedVillager,
|
||||
@NotNull OptimizationType optimizationType,
|
||||
@Nullable Player whoOptimised
|
||||
) throws IllegalArgumentException {
|
||||
this.wrappedVillager = wrappedVillager;
|
||||
this.whoOptimised = whoOptimised;
|
||||
if (optimizationType.equals(OptimizationType.NONE)) {
|
||||
|
@ -17,14 +17,23 @@ public class VillagerUnoptimizeEvent extends Event implements Cancellable {
|
||||
private final @Nullable Player whoUnoptimized;
|
||||
private boolean isCancelled = false;
|
||||
|
||||
public VillagerUnoptimizeEvent(@NotNull WrappedVillager wrappedVillager, @Nullable Player whoUnoptimized, @NotNull OptimizationType unOptimizeType, boolean isAsync) {
|
||||
public VillagerUnoptimizeEvent(
|
||||
@NotNull WrappedVillager wrappedVillager,
|
||||
@Nullable Player whoUnoptimized,
|
||||
@NotNull OptimizationType unOptimizeType,
|
||||
boolean isAsync
|
||||
) {
|
||||
super(isAsync);
|
||||
this.wrappedVillager = wrappedVillager;
|
||||
this.whoUnoptimized = whoUnoptimized;
|
||||
this.unOptimizeType = unOptimizeType;
|
||||
}
|
||||
|
||||
public VillagerUnoptimizeEvent(@NotNull WrappedVillager wrappedVillager, @Nullable Player whoUnoptimized, @NotNull OptimizationType unOptimizeType) {
|
||||
public VillagerUnoptimizeEvent(
|
||||
@NotNull WrappedVillager wrappedVillager,
|
||||
@Nullable Player whoUnoptimized,
|
||||
@NotNull OptimizationType unOptimizeType
|
||||
) {
|
||||
this.wrappedVillager = wrappedVillager;
|
||||
this.whoUnoptimized = whoUnoptimized;
|
||||
this.unOptimizeType = unOptimizeType;
|
||||
|
@ -1,29 +0,0 @@
|
||||
package me.xginko.villageroptimizer.models;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public final class ExpiringSet<E> {
|
||||
|
||||
private final Cache<E, Object> cache;
|
||||
private static final Object PRESENT = new Object(); // Dummy value to associate with an Object in the backing Cache
|
||||
|
||||
public ExpiringSet(long duration, TimeUnit unit) {
|
||||
this.cache = Caffeine.newBuilder().expireAfterWrite(duration, unit).build();
|
||||
}
|
||||
|
||||
public ExpiringSet(Duration duration) {
|
||||
this.cache = Caffeine.newBuilder().expireAfterWrite(duration).build();
|
||||
}
|
||||
|
||||
public void add(E item) {
|
||||
this.cache.put(item, PRESENT);
|
||||
}
|
||||
|
||||
public boolean contains(E item) {
|
||||
return this.cache.getIfPresent(item) != null;
|
||||
}
|
||||
}
|
@ -21,10 +21,8 @@ import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class VillagerChunkLimit implements VillagerOptimizerModule, Listener {
|
||||
|
||||
@ -41,23 +39,23 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener {
|
||||
this.scheduler = VillagerOptimizer.getFoliaLib().getImpl();
|
||||
this.villagerCache = VillagerOptimizer.getCache();
|
||||
Config config = VillagerOptimizer.getConfiguration();
|
||||
config.master().addComment("villager-chunk-limit.enable", """
|
||||
Checks chunks for too many villagers and removes excess villagers based on priority.""");
|
||||
this.check_period = config.getInt("villager-chunk-limit.check-period-in-ticks", 600, """
|
||||
Check all loaded chunks every X ticks. 1 second = 20 ticks\s
|
||||
A shorter delay in between checks is more efficient but is also more resource intense.\s
|
||||
A larger delay is less resource intense but could become inefficient.""");
|
||||
config.master().addComment("villager-chunk-limit.enable",
|
||||
"Checks chunks for too many villagers and removes excess villagers based on priority.");
|
||||
this.check_period = config.getInt("villager-chunk-limit.check-period-in-ticks", 600,
|
||||
"Check all loaded chunks every X ticks. 1 second = 20 ticks\n" +
|
||||
"A shorter delay in between checks is more efficient but is also more resource intense.\n" +
|
||||
"A larger delay is less resource intense but could become inefficient.");
|
||||
this.skip_unloaded_entity_chunks = config.getBoolean("villager-chunk-limit.skip-if-chunk-has-not-loaded-entities", true,
|
||||
"Does not check chunks that don't have their entities loaded.");
|
||||
this.log_enabled = config.getBoolean("villager-chunk-limit.log-removals", true);
|
||||
this.non_optimized_max_per_chunk = config.getInt("villager-chunk-limit.unoptimized.max-per-chunk", 20,
|
||||
"The maximum amount of unoptimized villagers per chunk.");
|
||||
this.non_optimized_removal_priority = config.getList("villager-chunk-limit.unoptimized.removal-priority", List.of(
|
||||
this.non_optimized_removal_priority = config.getList("villager-chunk-limit.unoptimized.removal-priority", Arrays.asList(
|
||||
"NONE", "NITWIT", "SHEPHERD", "FISHERMAN", "BUTCHER", "CARTOGRAPHER", "LEATHERWORKER",
|
||||
"FLETCHER", "MASON", "FARMER", "ARMORER", "TOOLSMITH", "WEAPONSMITH", "CLERIC", "LIBRARIAN"
|
||||
), """
|
||||
Professions that are in the top of the list are going to be scheduled for removal first.\s
|
||||
Use enums from https://jd.papermc.io/paper/1.20/org/bukkit/entity/Villager.Profession.html"""
|
||||
),
|
||||
"Professions that are in the top of the list are going to be scheduled for removal first.\n" +
|
||||
"Use enums from https://jd.papermc.io/paper/1.20/org/bukkit/entity/Villager.Profession.html"
|
||||
).stream().map(configuredProfession -> {
|
||||
try {
|
||||
return Villager.Profession.valueOf(configuredProfession);
|
||||
@ -67,10 +65,10 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener {
|
||||
"https://jd.papermc.io/paper/1.20/org/bukkit/entity/Villager.Profession.html.");
|
||||
return null;
|
||||
}
|
||||
}).filter(Objects::nonNull).toList();
|
||||
}).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
this.optimized_max_per_chunk = config.getInt("villager-chunk-limit.optimized.max-per-chunk", 60,
|
||||
"The maximum amount of optimized villagers per chunk.");
|
||||
this.optimized_removal_priority = config.getList("villager-chunk-limit.optimized.removal-priority", List.of(
|
||||
this.optimized_removal_priority = config.getList("villager-chunk-limit.optimized.removal-priority", Arrays.asList(
|
||||
"NONE", "NITWIT", "SHEPHERD", "FISHERMAN", "BUTCHER", "CARTOGRAPHER", "LEATHERWORKER",
|
||||
"FLETCHER", "MASON", "FARMER", "ARMORER", "TOOLSMITH", "WEAPONSMITH", "CLERIC", "LIBRARIAN"
|
||||
)).stream().map(configuredProfession -> {
|
||||
@ -82,7 +80,7 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener {
|
||||
"https://jd.papermc.io/paper/1.20/org/bukkit/entity/Villager.Profession.html.");
|
||||
return null;
|
||||
}
|
||||
}).filter(Objects::nonNull).toList();
|
||||
}).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -159,7 +157,7 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener {
|
||||
if (log_enabled) {
|
||||
VillagerOptimizer.getLog().info(Component.text(
|
||||
"Removed unoptimized villager with profession '" + villager.getProfession().name() + "' at " +
|
||||
CommonUtil.formatLocation(villager.getLocation())).color(VillagerOptimizer.plugin_style.color()));
|
||||
CommonUtil.formatLocation(villager.getLocation())).color(VillagerOptimizer.STYLE.color()));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -182,7 +180,7 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener {
|
||||
if (log_enabled) {
|
||||
VillagerOptimizer.getLog().info(Component.text("Removed optimized villager with profession '" +
|
||||
villager.getProfession().name() + "' at " +
|
||||
CommonUtil.formatLocation(villager.getLocation())).color(VillagerOptimizer.plugin_style.color()));
|
||||
CommonUtil.formatLocation(villager.getLocation())).color(VillagerOptimizer.STYLE.color()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ public class EnableLeashingVillagers implements VillagerOptimizerModule, Listene
|
||||
this.scheduler = VillagerOptimizer.getFoliaLib().getImpl();
|
||||
this.villagerCache = VillagerOptimizer.getCache();
|
||||
Config config = VillagerOptimizer.getConfiguration();
|
||||
config.master().addComment("gameplay.villagers-can-be-leashed.enable", """
|
||||
Enable leashing of villagers, enabling players to easily move villagers to where they want them to be.""");
|
||||
config.master().addComment("gameplay.villagers-can-be-leashed.enable",
|
||||
"Enable leashing of villagers, enabling players to easily move villagers to where they want them to be.");
|
||||
this.only_optimized = config.getBoolean("gameplay.villagers-can-be-leashed.only-optimized", false,
|
||||
"If set to true, only optimized villagers can be leashed.");
|
||||
this.log_enabled = config.getBoolean("gameplay.villagers-can-be-leashed.log", false);
|
||||
@ -86,7 +86,7 @@ public class EnableLeashingVillagers implements VillagerOptimizerModule, Listene
|
||||
|
||||
if (log_enabled) {
|
||||
VillagerOptimizer.getLog().info(Component.text(player.getName() + " leashed a villager at " +
|
||||
CommonUtil.formatLocation(villager.getLocation())).color(VillagerOptimizer.plugin_style.color()));
|
||||
CommonUtil.formatLocation(villager.getLocation())).color(VillagerOptimizer.STYLE.color()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import me.xginko.villageroptimizer.config.Config;
|
||||
import me.xginko.villageroptimizer.WrappedVillager;
|
||||
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
|
||||
import me.xginko.villageroptimizer.utils.CommonUtil;
|
||||
import me.xginko.villageroptimizer.utils.KyoriUtil;
|
||||
import net.kyori.adventure.text.TextReplacementConfig;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Villager;
|
||||
@ -34,13 +35,13 @@ public class LevelOptimizedProfession implements VillagerOptimizerModule, Listen
|
||||
this.scheduler = VillagerOptimizer.getFoliaLib().getImpl();
|
||||
this.villagerCache = VillagerOptimizer.getCache();
|
||||
Config config = VillagerOptimizer.getConfiguration();
|
||||
config.master().addComment("gameplay.level-optimized-profession", """
|
||||
This is needed to allow optimized villagers to level up.\s
|
||||
Temporarily enables the villagers AI to allow it to level up and then disables it again.""");
|
||||
config.master().addComment("gameplay.level-optimized-profession",
|
||||
"This is needed to allow optimized villagers to level up.\n" +
|
||||
"Temporarily enables the villagers AI to allow it to level up and then disables it again.");
|
||||
this.cooldown_millis = TimeUnit.SECONDS.toMillis(
|
||||
config.getInt("gameplay.level-optimized-profession.level-check-cooldown-seconds", 5, """
|
||||
Cooldown in seconds until the level of a villager will be checked and updated again.\s
|
||||
Recommended to leave as is."""));
|
||||
config.getInt("gameplay.level-optimized-profession.level-check-cooldown-seconds", 5,
|
||||
"Cooldown in seconds until the level of a villager will be checked and updated again.\n" +
|
||||
"Recommended to leave as is."));
|
||||
this.notify_player = config.getBoolean("gameplay.level-optimized-profession.notify-player", true,
|
||||
"Tell players to wait when a villager is leveling up.");
|
||||
}
|
||||
@ -61,12 +62,13 @@ public class LevelOptimizedProfession implements VillagerOptimizerModule, Listen
|
||||
return true;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
private void onTradeScreenClose(InventoryCloseEvent event) {
|
||||
if (
|
||||
event.getInventory().getType().equals(InventoryType.MERCHANT)
|
||||
&& event.getInventory().getHolder() instanceof Villager villager
|
||||
&& event.getInventory().getHolder() instanceof Villager
|
||||
) {
|
||||
Villager villager = (Villager) event.getInventory().getHolder();
|
||||
WrappedVillager wVillager = villagerCache.getOrAdd(villager);
|
||||
if (!wVillager.isOptimized()) return;
|
||||
|
||||
@ -89,7 +91,8 @@ public class LevelOptimizedProfession implements VillagerOptimizerModule, Listen
|
||||
.matchLiteral("%time%")
|
||||
.replacement(CommonUtil.formatDuration(Duration.ofMillis(wVillager.getLevelCooldownMillis(cooldown_millis))))
|
||||
.build();
|
||||
VillagerOptimizer.getLang(player.locale()).villager_leveling_up.forEach(line -> player.sendMessage(line.replaceText(timeLeft)));
|
||||
VillagerOptimizer.getLang(player.locale()).villager_leveling_up
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(timeLeft)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,16 +27,16 @@ public class MakeVillagersSpawnAdult implements VillagerOptimizerModule, Listene
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
return VillagerOptimizer.getConfiguration().getBoolean("gameplay.villagers-spawn-as-adults.enable", false, """
|
||||
Spawned villagers will immediately be adults.\s
|
||||
This is to save some more resources as players don't have to keep unoptimized\s
|
||||
villagers loaded because they have to wait for them to turn into adults before they can\s
|
||||
optimize them.""");
|
||||
return VillagerOptimizer.getConfiguration().getBoolean("gameplay.villagers-spawn-as-adults.enable", false,
|
||||
"Spawned villagers will immediately be adults.\n" +
|
||||
"This is to save some more resources as players don't have to keep unoptimized\n" +
|
||||
"villagers loaded because they have to wait for them to turn into adults before they can\n" +
|
||||
"optimize them.");
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
private void onVillagerSpawn(CreatureSpawnEvent event) {
|
||||
if (event.getEntityType() == EntityType.VILLAGER) {
|
||||
if (event.getEntityType().equals(EntityType.VILLAGER)) {
|
||||
Villager villager = (Villager) event.getEntity();
|
||||
if (!villager.isAdult()) villager.setAdult();
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public class PreventOptimizedDamage implements VillagerOptimizerModule, Listener
|
||||
|
||||
private final VillagerCache villagerCache;
|
||||
private final Set<EntityDamageEvent.DamageCause> damage_causes_to_cancel;
|
||||
private final boolean cancelKnockback;
|
||||
private final boolean cancel_knockback;
|
||||
|
||||
public PreventOptimizedDamage() {
|
||||
shouldEnable();
|
||||
@ -31,13 +31,13 @@ public class PreventOptimizedDamage implements VillagerOptimizerModule, Listener
|
||||
Config config = VillagerOptimizer.getConfiguration();
|
||||
config.master().addComment("gameplay.prevent-damage-to-optimized.enable",
|
||||
"Configure what kind of damage you want to cancel for optimized villagers here.");
|
||||
this.cancelKnockback = config.getBoolean("gameplay.prevent-damage-to-optimized.prevent-knockback-from-entity", true,
|
||||
this.cancel_knockback = config.getBoolean("gameplay.prevent-damage-to-optimized.prevent-knockback-from-entity", true,
|
||||
"Prevents optimized villagers from getting knocked back by an attacking entity");
|
||||
this.damage_causes_to_cancel = config.getList("gameplay.prevent-damage-to-optimized.damage-causes-to-cancel",
|
||||
Arrays.stream(EntityDamageEvent.DamageCause.values()).map(Enum::name).sorted().toList(), """
|
||||
These are all current entries in the game. Remove what you do not need blocked.\s
|
||||
If you want a description or need to add a previously removed type, refer to:\s
|
||||
https://jd.papermc.io/paper/1.20/org/bukkit/event/entity/EntityDamageEvent.DamageCause.html"""
|
||||
Arrays.stream(EntityDamageEvent.DamageCause.values()).map(Enum::name).sorted().collect(Collectors.toList()),
|
||||
"These are all current entries in the game. Remove what you do not need blocked.\n" +
|
||||
"If you want a description or need to add a previously removed type, refer to:\n" +
|
||||
"https://jd.papermc.io/paper/1.20/org/bukkit/event/entity/EntityDamageEvent.DamageCause.html"
|
||||
).stream().map(configuredDamageCause -> {
|
||||
try {
|
||||
return EntityDamageEvent.DamageCause.valueOf(configuredDamageCause);
|
||||
@ -80,7 +80,7 @@ public class PreventOptimizedDamage implements VillagerOptimizerModule, Listener
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
private void onKnockbackByEntity(EntityKnockbackByEntityEvent event) {
|
||||
if (
|
||||
cancelKnockback
|
||||
cancel_knockback
|
||||
&& event.getEntityType().equals(EntityType.VILLAGER)
|
||||
&& villagerCache.getOrAdd((Villager) event.getEntity()).isOptimized()
|
||||
) {
|
||||
|
@ -42,11 +42,10 @@ public class PreventOptimizedTargeting implements VillagerOptimizerModule, Liste
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
private void onTarget(EntityTargetEvent event) {
|
||||
// Yes, instanceof checks would look way more beautiful here but checking type is much faster
|
||||
Entity target = event.getTarget();
|
||||
if (
|
||||
target != null
|
||||
&& target.getType() == EntityType.VILLAGER
|
||||
&& target.getType().equals(EntityType.VILLAGER)
|
||||
&& villagerCache.getOrAdd((Villager) target).isOptimized()
|
||||
) {
|
||||
event.setTarget(null);
|
||||
@ -59,7 +58,7 @@ public class PreventOptimizedTargeting implements VillagerOptimizerModule, Liste
|
||||
Entity target = event.getTargetEntity();
|
||||
if (
|
||||
target != null
|
||||
&& target.getType() == EntityType.VILLAGER
|
||||
&& target.getType().equals(EntityType.VILLAGER)
|
||||
&& villagerCache.getOrAdd((Villager) target).isOptimized()
|
||||
) {
|
||||
event.setCancelled(true);
|
||||
@ -69,11 +68,11 @@ public class PreventOptimizedTargeting implements VillagerOptimizerModule, Liste
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
private void onEntityAttackVillager(EntityDamageByEntityEvent event) {
|
||||
if (
|
||||
event.getEntityType() == EntityType.VILLAGER
|
||||
&& event.getDamager() instanceof Mob attacker
|
||||
event.getEntityType().equals(EntityType.VILLAGER)
|
||||
&& event.getDamager() instanceof Mob
|
||||
&& villagerCache.getOrAdd((Villager) event.getEntity()).isOptimized()
|
||||
) {
|
||||
attacker.setTarget(null);
|
||||
((Mob) event.getDamager()).setTarget(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import me.xginko.villageroptimizer.VillagerCache;
|
||||
import me.xginko.villageroptimizer.config.Config;
|
||||
import me.xginko.villageroptimizer.enums.permissions.Bypass;
|
||||
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
|
||||
import me.xginko.villageroptimizer.utils.KyoriUtil;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Villager;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@ -24,10 +25,10 @@ public class PreventUnoptimizedTrading implements VillagerOptimizerModule, Liste
|
||||
shouldEnable();
|
||||
this.villagerCache = VillagerOptimizer.getCache();
|
||||
Config config = VillagerOptimizer.getConfiguration();
|
||||
config.master().addComment("gameplay.prevent-trading-with-unoptimized.enable", """
|
||||
Will prevent players from selecting and using trades of unoptimized villagers.\s
|
||||
Use this if you have a lot of villagers and therefore want to force your players to optimize them.\s
|
||||
Inventories can still be opened so players can move villagers around.""");
|
||||
config.master().addComment("gameplay.prevent-trading-with-unoptimized.enable",
|
||||
"Will prevent players from selecting and using trades of unoptimized villagers.\n" +
|
||||
"Use this if you have a lot of villagers and therefore want to force your players to optimize them.\n" +
|
||||
"Inventories can still be opened so players can move villagers around.");
|
||||
this.notify_player = config.getBoolean("gameplay.prevent-trading-with-unoptimized.notify-player", true,
|
||||
"Sends players a message when they try to trade with an unoptimized villager.");
|
||||
}
|
||||
@ -48,36 +49,38 @@ public class PreventUnoptimizedTrading implements VillagerOptimizerModule, Liste
|
||||
return VillagerOptimizer.getConfiguration().getBoolean("gameplay.prevent-trading-with-unoptimized.enable", false);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
private void onTradeOpen(TradeSelectEvent event) {
|
||||
if (!event.getInventory().getType().equals(InventoryType.MERCHANT)) return;
|
||||
if (event.getWhoClicked().hasPermission(Bypass.TRADE_PREVENTION.get())) return;
|
||||
if (!(event.getInventory().getHolder() instanceof Villager)) return;
|
||||
|
||||
if (
|
||||
event.getInventory().getType().equals(InventoryType.MERCHANT)
|
||||
&& event.getInventory().getHolder() instanceof Villager villager
|
||||
&& !villagerCache.getOrAdd(villager).isOptimized()
|
||||
) {
|
||||
Villager villager = (Villager) event.getInventory().getHolder();
|
||||
|
||||
if (!villagerCache.getOrAdd(villager).isOptimized()) {
|
||||
event.setCancelled(true);
|
||||
if (notify_player) {
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
VillagerOptimizer.getLang(player.locale()).optimize_for_trading.forEach(player::sendMessage);
|
||||
VillagerOptimizer.getLang(player.locale()).optimize_for_trading
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
private void onInventoryClick(InventoryClickEvent event) {
|
||||
if (!event.getInventory().getType().equals(InventoryType.MERCHANT)) return;
|
||||
if (event.getWhoClicked().hasPermission(Bypass.TRADE_PREVENTION.get())) return;
|
||||
if (!(event.getInventory().getHolder() instanceof Villager)) return;
|
||||
|
||||
if (
|
||||
event.getInventory().getType().equals(InventoryType.MERCHANT)
|
||||
&& event.getInventory().getHolder() instanceof Villager villager
|
||||
&& !villagerCache.getOrAdd(villager).isOptimized()
|
||||
) {
|
||||
Villager villager = (Villager) event.getInventory().getHolder();
|
||||
|
||||
if (!villagerCache.getOrAdd(villager).isOptimized()) {
|
||||
event.setCancelled(true);
|
||||
if (notify_player) {
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
VillagerOptimizer.getLang(player.locale()).optimize_for_trading.forEach(player::sendMessage);
|
||||
VillagerOptimizer.getLang(player.locale()).optimize_for_trading
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,10 +25,11 @@ public class RenameOptimizedVillagers implements VillagerOptimizerModule, Listen
|
||||
shouldEnable();
|
||||
this.scheduler = VillagerOptimizer.getFoliaLib().getImpl();
|
||||
Config config = VillagerOptimizer.getConfiguration();
|
||||
config.master().addComment("gameplay.rename-optimized-villagers.enable", """
|
||||
Will change a villager's name to the name configured below when they are optimized.\s
|
||||
These names will be removed when unoptimized again if they were not changed in the meantime.""");
|
||||
this.optimized_name = MiniMessage.miniMessage().deserialize(config.getString("gameplay.rename-optimized-villagers.optimized-name", "<green>Optimized",
|
||||
config.master().addComment("gameplay.rename-optimized-villagers.enable",
|
||||
"Will change a villager's name to the name configured below when they are optimized.\n" +
|
||||
"These names will be removed when unoptimized again if they were not changed in the meantime.");
|
||||
this.optimized_name = MiniMessage.miniMessage().deserialize(
|
||||
config.getString("gameplay.rename-optimized-villagers.optimized-name", "<green>Optimized",
|
||||
"The name that will be used to mark optimized villagers. Uses MiniMessage format."));
|
||||
this.overwrite_previous_name = config.getBoolean("gameplay.rename-optimized-villagers.overwrite-existing-name", false,
|
||||
"If set to true, will rename even if the villager has already been named.");
|
||||
|
@ -7,9 +7,9 @@ import me.xginko.villageroptimizer.config.Config;
|
||||
import me.xginko.villageroptimizer.enums.permissions.Bypass;
|
||||
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
|
||||
import me.xginko.villageroptimizer.utils.CommonUtil;
|
||||
import me.xginko.villageroptimizer.utils.KyoriUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextReplacementConfig;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Villager;
|
||||
@ -31,9 +31,9 @@ public class RestockOptimizedTrades implements VillagerOptimizerModule, Listener
|
||||
shouldEnable();
|
||||
this.villagerCache = VillagerOptimizer.getCache();
|
||||
Config config = VillagerOptimizer.getConfiguration();
|
||||
config.master().addComment("gameplay.restock-optimized-trades", """
|
||||
This is for automatic restocking of trades for optimized villagers. Optimized Villagers\s
|
||||
don't have enough AI to restock their trades naturally, so this is here as a workaround.""");
|
||||
config.master().addComment("gameplay.restock-optimized-trades",
|
||||
"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.");
|
||||
this.restock_delay_millis = config.getInt("gameplay.restock-optimized-trades.delay-in-ticks", 1000,
|
||||
"1 second = 20 ticks. There are 24.000 ticks in a single minecraft day.") * 50L;
|
||||
this.notify_player = config.getBoolean("gameplay.restock-optimized-trades.notify-player", true,
|
||||
@ -70,18 +70,19 @@ public class RestockOptimizedTrades implements VillagerOptimizerModule, Listener
|
||||
if (wVillager.canRestock(restock_delay_millis) || player_bypassing) {
|
||||
wVillager.restock();
|
||||
wVillager.saveRestockTime();
|
||||
|
||||
if (notify_player && !player_bypassing) {
|
||||
final TextReplacementConfig timeLeft = TextReplacementConfig.builder()
|
||||
.matchLiteral("%time%")
|
||||
.replacement(CommonUtil.formatDuration(Duration.ofMillis(wVillager.getRestockCooldownMillis(restock_delay_millis))))
|
||||
.build();
|
||||
VillagerOptimizer.getLang(player.locale()).trades_restocked.forEach(line -> player.sendMessage(line.replaceText(timeLeft)));
|
||||
VillagerOptimizer.getLang(player.locale()).trades_restocked
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(timeLeft)));
|
||||
}
|
||||
|
||||
if (log_enabled) {
|
||||
final Location location = wVillager.villager().getLocation();
|
||||
VillagerOptimizer.getLog().info(Component.text("Restocked optimized villager at " +
|
||||
"x=" + location.getBlockX() + ", y=" + location.getBlockY() + ", z=" + location.getBlockZ() +
|
||||
", world=" + location.getWorld().getName()).style(VillagerOptimizer.plugin_style));
|
||||
CommonUtil.formatLocation(wVillager.villager().getLocation())).style(VillagerOptimizer.STYLE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import me.xginko.villageroptimizer.events.VillagerOptimizeEvent;
|
||||
import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent;
|
||||
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
|
||||
import me.xginko.villageroptimizer.utils.CommonUtil;
|
||||
import me.xginko.villageroptimizer.utils.KyoriUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextReplacementConfig;
|
||||
import org.bukkit.Location;
|
||||
@ -28,8 +29,8 @@ import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -47,10 +48,10 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener {
|
||||
shouldEnable();
|
||||
this.villagerCache = VillagerOptimizer.getCache();
|
||||
Config config = VillagerOptimizer.getConfiguration();
|
||||
config.master().addComment("optimization-methods.block-optimization.enable", """
|
||||
When enabled, the closest villager standing near a configured block being placed will be optimized.\s
|
||||
If a configured block is broken nearby, the closest villager will become unoptimized again.""");
|
||||
this.blocks_that_disable = config.getList("optimization-methods.block-optimization.materials", List.of(
|
||||
config.master().addComment("optimization-methods.block-optimization.enable",
|
||||
"When enabled, the closest villager standing near a configured block being placed will be optimized.\n" +
|
||||
"If a configured block is broken nearby, the closest villager will become unoptimized again.");
|
||||
this.blocks_that_disable = config.getList("optimization-methods.block-optimization.materials", Arrays.asList(
|
||||
"LAPIS_BLOCK", "GLOWSTONE", "IRON_BLOCK"
|
||||
), "Values here need to be valid bukkit Material enums for your server version."
|
||||
).stream().map(configuredMaterial -> {
|
||||
@ -64,12 +65,12 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener {
|
||||
}
|
||||
}).filter(Objects::nonNull).collect(Collectors.toCollection(HashSet::new));
|
||||
this.cooldown_millis = TimeUnit.SECONDS.toMillis(
|
||||
config.getInt("optimization-methods.block-optimization.optimize-cooldown-seconds", 600, """
|
||||
Cooldown in seconds until a villager can be optimized again by using specific blocks.\s
|
||||
Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior."""));
|
||||
this.search_radius = config.getDouble("optimization-methods.block-optimization.search-radius-in-blocks", 2.0, """
|
||||
The radius in blocks a villager can be away from the player when he places an optimize block.\s
|
||||
The closest unoptimized villager to the player will be optimized.""") / 2;
|
||||
config.getInt("optimization-methods.block-optimization.optimize-cooldown-seconds", 600,
|
||||
"Cooldown in seconds until a villager can be optimized again by using specific blocks.\n" +
|
||||
"Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior."));
|
||||
this.search_radius = config.getDouble("optimization-methods.block-optimization.search-radius-in-blocks", 2.0,
|
||||
"The radius in blocks a villager can be away from the player when he places an optimize block.\n" +
|
||||
"The closest unoptimized villager to the player will be optimized.") / 2;
|
||||
this.only_while_sneaking = config.getBoolean("optimization-methods.block-optimization.only-when-sneaking", true,
|
||||
"Only optimize/unoptimize by workstation when player is sneaking during place or break.");
|
||||
this.notify_player = config.getBoolean("optimization-methods.block-optimization.notify-player", true,
|
||||
@ -123,7 +124,13 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener {
|
||||
if (closestOptimizableVillager == null) return;
|
||||
|
||||
if (closestOptimizableVillager.canOptimize(cooldown_millis) || player.hasPermission(Bypass.BLOCK_COOLDOWN.get())) {
|
||||
VillagerOptimizeEvent optimizeEvent = new VillagerOptimizeEvent(closestOptimizableVillager, OptimizationType.BLOCK, player, event.isAsynchronous());
|
||||
VillagerOptimizeEvent optimizeEvent = new VillagerOptimizeEvent(
|
||||
closestOptimizableVillager,
|
||||
OptimizationType.BLOCK,
|
||||
player,
|
||||
event.isAsynchronous()
|
||||
);
|
||||
|
||||
if (!optimizeEvent.callEvent()) return;
|
||||
|
||||
closestOptimizableVillager.setOptimizationType(optimizeEvent.getOptimizationType());
|
||||
@ -138,15 +145,13 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener {
|
||||
.matchLiteral("%blocktype%")
|
||||
.replacement(placed.getType().toString().toLowerCase())
|
||||
.build();
|
||||
VillagerOptimizer.getLang(player.locale()).block_optimize_success.forEach(line -> player.sendMessage(line
|
||||
.replaceText(vilProfession)
|
||||
.replaceText(placedMaterial)
|
||||
));
|
||||
VillagerOptimizer.getLang(player.locale()).block_optimize_success
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(vilProfession).replaceText(placedMaterial)));
|
||||
}
|
||||
|
||||
if (log_enabled) {
|
||||
VillagerOptimizer.getLog().info(Component.text(player.getName() + " optimized villager by block at " +
|
||||
CommonUtil.formatLocation(closestOptimizableVillager.villager().getLocation())).color(VillagerOptimizer.plugin_style.color()));
|
||||
CommonUtil.formatLocation(closestOptimizableVillager.villager().getLocation())).color(VillagerOptimizer.STYLE.color()));
|
||||
}
|
||||
} else {
|
||||
CommonUtil.shakeHead(closestOptimizableVillager.villager());
|
||||
@ -155,7 +160,8 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener {
|
||||
.matchLiteral("%time%")
|
||||
.replacement(CommonUtil.formatDuration(Duration.ofMillis(closestOptimizableVillager.getOptimizeCooldownMillis(cooldown_millis))))
|
||||
.build();
|
||||
VillagerOptimizer.getLang(player.locale()).block_on_optimize_cooldown.forEach(line -> player.sendMessage(line.replaceText(timeLeft)));
|
||||
VillagerOptimizer.getLang(player.locale()).block_on_optimize_cooldown
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(timeLeft)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -187,7 +193,13 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener {
|
||||
|
||||
if (closestOptimizedVillager == null) return;
|
||||
|
||||
VillagerUnoptimizeEvent unOptimizeEvent = new VillagerUnoptimizeEvent(closestOptimizedVillager, player, OptimizationType.BLOCK, event.isAsynchronous());
|
||||
VillagerUnoptimizeEvent unOptimizeEvent = new VillagerUnoptimizeEvent(
|
||||
closestOptimizedVillager,
|
||||
player,
|
||||
OptimizationType.BLOCK,
|
||||
event.isAsynchronous()
|
||||
);
|
||||
|
||||
if (!unOptimizeEvent.callEvent()) return;
|
||||
|
||||
closestOptimizedVillager.setOptimizationType(OptimizationType.NONE);
|
||||
@ -201,15 +213,13 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener {
|
||||
.matchLiteral("%blocktype%")
|
||||
.replacement(broken.getType().toString().toLowerCase())
|
||||
.build();
|
||||
VillagerOptimizer.getLang(player.locale()).block_unoptimize_success.forEach(line -> player.sendMessage(line
|
||||
.replaceText(vilProfession)
|
||||
.replaceText(brokenMaterial)
|
||||
));
|
||||
VillagerOptimizer.getLang(player.locale()).block_unoptimize_success
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(vilProfession).replaceText(brokenMaterial)));
|
||||
}
|
||||
|
||||
if (log_enabled) {
|
||||
VillagerOptimizer.getLog().info(Component.text(player.getName() + " unoptimized villager by block at " +
|
||||
CommonUtil.formatLocation(closestOptimizedVillager.villager().getLocation())).color(VillagerOptimizer.plugin_style.color()));
|
||||
CommonUtil.formatLocation(closestOptimizedVillager.villager().getLocation())).color(VillagerOptimizer.STYLE.color()));
|
||||
}
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ import me.xginko.villageroptimizer.events.VillagerOptimizeEvent;
|
||||
import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent;
|
||||
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
|
||||
import me.xginko.villageroptimizer.utils.CommonUtil;
|
||||
import me.xginko.villageroptimizer.utils.KyoriUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextReplacementConfig;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
@ -27,13 +28,15 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class OptimizeByNametag implements VillagerOptimizerModule, Listener {
|
||||
|
||||
private final PlainTextComponentSerializer plainTextSerializer;
|
||||
private final VillagerCache villagerCache;
|
||||
private final Set<String> nametags;
|
||||
private final long cooldown;
|
||||
@ -41,19 +44,21 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener {
|
||||
|
||||
public OptimizeByNametag() {
|
||||
shouldEnable();
|
||||
this.plainTextSerializer = PlainTextComponentSerializer.plainText();
|
||||
this.villagerCache = VillagerOptimizer.getCache();
|
||||
Config config = VillagerOptimizer.getConfiguration();
|
||||
config.master().addComment("optimization-methods.nametag-optimization.enable", """
|
||||
Enable optimization by naming villagers to one of the names configured below.\s
|
||||
Nametag optimized villagers will be unoptimized again when they are renamed to something else.""");
|
||||
this.nametags = config.getList("optimization-methods.nametag-optimization.names", List.of("Optimize", "DisableAI"),
|
||||
config.master().addComment("optimization-methods.nametag-optimization.enable",
|
||||
"Enable optimization by naming villagers to one of the names configured below.\n" +
|
||||
"Nametag optimized villagers will be unoptimized again when they are renamed to something else.");
|
||||
this.nametags = config.getList("optimization-methods.nametag-optimization.names", Arrays.asList("Optimize", "DisableAI"),
|
||||
"Names are case insensitive, capital letters won't matter.")
|
||||
.stream().map(String::toLowerCase).collect(Collectors.toCollection(HashSet::new));
|
||||
this.consume_nametag = config.getBoolean("optimization-methods.nametag-optimization.nametags-get-consumed", true,
|
||||
"Enable or disable consumption of the used nametag item.");
|
||||
this.cooldown = config.getInt("optimization-methods.nametag-optimization.optimize-cooldown-seconds", 600, """
|
||||
Cooldown in seconds until a villager can be optimized again using a nametag.\s
|
||||
Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior.""") * 1000L;
|
||||
this.cooldown = TimeUnit.SECONDS.toMillis(
|
||||
config.getInt("optimization-methods.nametag-optimization.optimize-cooldown-seconds", 600,
|
||||
"Cooldown in seconds until a villager can be optimized again using a nametag.\n" +
|
||||
"Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior."));
|
||||
this.notify_player = config.getBoolean("optimization-methods.nametag-optimization.notify-player", true,
|
||||
"Sends players a message when they successfully optimized a villager.");
|
||||
this.log_enabled = config.getBoolean("optimization-methods.nametag-optimization.log", false);
|
||||
@ -82,20 +87,27 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener {
|
||||
if (!player.hasPermission(Optimize.NAMETAG.get())) return;
|
||||
|
||||
ItemStack usedItem = player.getInventory().getItem(event.getHand());
|
||||
if (!usedItem.getType().equals(Material.NAME_TAG)) return;
|
||||
if (usedItem != null && !usedItem.getType().equals(Material.NAME_TAG)) return;
|
||||
if (!usedItem.hasItemMeta()) return;
|
||||
ItemMeta meta = usedItem.getItemMeta();
|
||||
if (!meta.hasDisplayName()) return;
|
||||
|
||||
// Get component name first, so we can manually name the villager when canceling the event to avoid item consumption.
|
||||
Component newVillagerName = meta.displayName();
|
||||
assert newVillagerName != null; // Legitimate since we checked for hasDisplayName()
|
||||
final String name = PlainTextComponentSerializer.plainText().serialize(newVillagerName);
|
||||
final String name = plainTextSerializer.serialize(newVillagerName);
|
||||
Villager villager = (Villager) event.getRightClicked();
|
||||
WrappedVillager wVillager = villagerCache.getOrAdd(villager);
|
||||
|
||||
if (nametags.contains(name.toLowerCase())) {
|
||||
if (wVillager.canOptimize(cooldown) || player.hasPermission(Bypass.NAMETAG_COOLDOWN.get())) {
|
||||
VillagerOptimizeEvent optimizeEvent = new VillagerOptimizeEvent(wVillager, OptimizationType.NAMETAG, player, event.isAsynchronous());
|
||||
VillagerOptimizeEvent optimizeEvent = new VillagerOptimizeEvent(
|
||||
wVillager,
|
||||
OptimizationType.NAMETAG,
|
||||
player,
|
||||
event.isAsynchronous()
|
||||
);
|
||||
|
||||
if (!optimizeEvent.callEvent()) return;
|
||||
|
||||
if (!consume_nametag) {
|
||||
@ -107,13 +119,14 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener {
|
||||
wVillager.saveOptimizeTime();
|
||||
|
||||
if (notify_player) {
|
||||
VillagerOptimizer.getLang(player.locale()).nametag_optimize_success.forEach(player::sendMessage);
|
||||
VillagerOptimizer.getLang(player.locale()).nametag_optimize_success
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line));
|
||||
}
|
||||
|
||||
if (log_enabled) {
|
||||
VillagerOptimizer.getLog().info(Component.text(player.getName() +
|
||||
" optimized villager by nametag '" + name + "' at " +
|
||||
CommonUtil.formatLocation(wVillager.villager().getLocation())).color(VillagerOptimizer.plugin_style.color()));
|
||||
CommonUtil.formatLocation(wVillager.villager().getLocation())).color(VillagerOptimizer.STYLE.color()));
|
||||
}
|
||||
} else {
|
||||
event.setCancelled(true);
|
||||
@ -123,7 +136,8 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener {
|
||||
.matchLiteral("%time%")
|
||||
.replacement(CommonUtil.formatDuration(Duration.ofMillis(wVillager.getOptimizeCooldownMillis(cooldown))))
|
||||
.build();
|
||||
VillagerOptimizer.getLang(player.locale()).nametag_on_optimize_cooldown.forEach(line -> player.sendMessage(line.replaceText(timeLeft)));
|
||||
VillagerOptimizer.getLang(player.locale()).nametag_on_optimize_cooldown
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(timeLeft)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -134,13 +148,14 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener {
|
||||
wVillager.setOptimizationType(OptimizationType.NONE);
|
||||
|
||||
if (notify_player) {
|
||||
VillagerOptimizer.getLang(player.locale()).nametag_unoptimize_success.forEach(player::sendMessage);
|
||||
VillagerOptimizer.getLang(player.locale()).nametag_unoptimize_success
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line));
|
||||
}
|
||||
|
||||
if (log_enabled) {
|
||||
VillagerOptimizer.getLog().info(Component.text(player.getName() +
|
||||
" unoptimized villager by nametag '" + name + "' at " +
|
||||
CommonUtil.formatLocation(wVillager.villager().getLocation())).color(VillagerOptimizer.plugin_style.color()));
|
||||
CommonUtil.formatLocation(wVillager.villager().getLocation())).color(VillagerOptimizer.STYLE.color()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import me.xginko.villageroptimizer.events.VillagerOptimizeEvent;
|
||||
import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent;
|
||||
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
|
||||
import me.xginko.villageroptimizer.utils.CommonUtil;
|
||||
import me.xginko.villageroptimizer.utils.KyoriUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextReplacementConfig;
|
||||
import org.bukkit.Location;
|
||||
@ -48,27 +49,27 @@ public class OptimizeByWorkstation implements VillagerOptimizerModule, Listener
|
||||
this.scheduler = VillagerOptimizer.getFoliaLib().getImpl();
|
||||
this.villagerCache = VillagerOptimizer.getCache();
|
||||
Config config = VillagerOptimizer.getConfiguration();
|
||||
config.master().addComment("optimization-methods.workstation-optimization.enable", """
|
||||
When enabled, villagers that have a job and have been traded with at least once will become optimized,\s
|
||||
if near their workstation. If the workstation is broken, the villager will become unoptimized again.""");
|
||||
this.delay_millis = Math.max(config.getInt("optimization-methods.workstation-optimization.delay.default-delay-in-ticks", 10, """
|
||||
The delay in ticks the plugin should wait before trying to optimize the closest villager on workstation place.\s
|
||||
Gives the villager time to claim the placed workstation. Minimum delay is 1 Tick (Not recommended)"""), 1) * 50L;
|
||||
this.resettable_delay_millis = Math.max(config.getInt("optimization-methods.workstation-optimization.delay.resettable-delay-in-ticks", 60, """
|
||||
The delay in ticks the plugin should wait before trying to optimize a villager that can loose its profession\s
|
||||
by having their workstation destroyed.\s
|
||||
Intended to fix issues while trade rolling."""), 1) * 50L;
|
||||
config.master().addComment("optimization-methods.workstation-optimization.enable",
|
||||
"When enabled, villagers that have a job and have been traded with at least once will become optimized,\n" +
|
||||
"if near their workstation. If the workstation is broken, the villager will become unoptimized again.");
|
||||
this.delay_millis = Math.max(config.getInt("optimization-methods.workstation-optimization.delay.default-delay-in-ticks", 10,
|
||||
"The delay in ticks the plugin should wait before trying to optimize the closest villager on workstation place.\n" +
|
||||
"Gives the villager time to claim the placed workstation. Minimum delay is 1 Tick (Not recommended)"), 1) * 50L;
|
||||
this.resettable_delay_millis = Math.max(config.getInt("optimization-methods.workstation-optimization.delay.resettable-delay-in-ticks", 60,
|
||||
"The delay in ticks the plugin should wait before trying to optimize a villager that can loose its profession\n" +
|
||||
"by having their workstation destroyed.\n" +
|
||||
"Intended to fix issues while trade rolling."), 1) * 50L;
|
||||
this.pending_optimizations = Caffeine.newBuilder()
|
||||
.expireAfterWrite(Duration.ofMillis(Math.max(resettable_delay_millis, delay_millis) + 500L))
|
||||
.build();
|
||||
this.search_radius = config.getDouble("optimization-methods.workstation-optimization.search-radius-in-blocks", 2.0, """
|
||||
The radius in blocks a villager can be away from the player when he places a workstation.\s
|
||||
The closest unoptimized villager to the player will be optimized.""");
|
||||
this.search_radius = config.getDouble("optimization-methods.workstation-optimization.search-radius-in-blocks", 2.0,
|
||||
"The radius in blocks a villager can be away from the player when he places a workstation.\n" +
|
||||
"The closest unoptimized villager to the player will be optimized.");
|
||||
this.search_radius_squared = NumberConversions.square(search_radius);
|
||||
this.cooldown_millis = TimeUnit.SECONDS.toMillis(
|
||||
config.getInt("optimization-methods.workstation-optimization.optimize-cooldown-seconds", 600, """
|
||||
Cooldown in seconds until a villager can be optimized again using a workstation.\s
|
||||
Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior."""));
|
||||
config.getInt("optimization-methods.workstation-optimization.optimize-cooldown-seconds", 600,
|
||||
"Cooldown in seconds until a villager can be optimized again using a workstation.\n" +
|
||||
"Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior."));
|
||||
this.only_while_sneaking = config.getBoolean("optimization-methods.workstation-optimization.only-when-sneaking", true,
|
||||
"Only optimize/unoptimize by workstation when player is sneaking during place or break");
|
||||
this.notify_player = config.getBoolean("optimization-methods.workstation-optimization.notify-player", true,
|
||||
@ -132,14 +133,19 @@ public class OptimizeByWorkstation implements VillagerOptimizerModule, Listener
|
||||
.matchLiteral("%time%")
|
||||
.replacement(CommonUtil.formatDuration(Duration.ofMillis(finalToOptimize.getOptimizeCooldownMillis(cooldown_millis))))
|
||||
.build();
|
||||
VillagerOptimizer.getLang(player.locale()).nametag_on_optimize_cooldown.forEach(line -> player.sendMessage(line
|
||||
.replaceText(timeLeft)
|
||||
));
|
||||
VillagerOptimizer.getLang(player.locale()).nametag_on_optimize_cooldown
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(timeLeft)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VillagerOptimizeEvent optimizeEvent = new VillagerOptimizeEvent(finalToOptimize, OptimizationType.WORKSTATION, player, event.isAsynchronous());
|
||||
VillagerOptimizeEvent optimizeEvent = new VillagerOptimizeEvent(
|
||||
finalToOptimize,
|
||||
OptimizationType.WORKSTATION,
|
||||
player,
|
||||
event.isAsynchronous()
|
||||
);
|
||||
|
||||
if (!optimizeEvent.callEvent()) return;
|
||||
|
||||
finalToOptimize.setOptimizationType(optimizeEvent.getOptimizationType());
|
||||
@ -154,16 +160,14 @@ public class OptimizeByWorkstation implements VillagerOptimizerModule, Listener
|
||||
.matchLiteral("%workstation%")
|
||||
.replacement(placed.getType().toString().toLowerCase())
|
||||
.build();
|
||||
VillagerOptimizer.getLang(player.locale()).workstation_optimize_success.forEach(line -> player.sendMessage(line
|
||||
.replaceText(vilProfession)
|
||||
.replaceText(placedWorkstation)
|
||||
));
|
||||
VillagerOptimizer.getLang(player.locale()).workstation_optimize_success
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(vilProfession).replaceText(placedWorkstation)));
|
||||
}
|
||||
|
||||
if (log_enabled) {
|
||||
VillagerOptimizer.getLog().info(Component.text(player.getName() +
|
||||
" optimized villager by workstation (" + placed.getType().toString().toLowerCase() + ") at " +
|
||||
CommonUtil.formatLocation(finalToOptimize.villager().getLocation())).color(VillagerOptimizer.plugin_style.color()));
|
||||
CommonUtil.formatLocation(finalToOptimize.villager().getLocation())).color(VillagerOptimizer.STYLE.color()));
|
||||
}
|
||||
}, toOptimize.canLooseProfession() ? resettable_delay_millis : delay_millis, TimeUnit.MILLISECONDS));
|
||||
}
|
||||
@ -201,7 +205,13 @@ public class OptimizeByWorkstation implements VillagerOptimizerModule, Listener
|
||||
|
||||
if (closestOptimizedVillager == null) return;
|
||||
|
||||
VillagerUnoptimizeEvent unOptimizeEvent = new VillagerUnoptimizeEvent(closestOptimizedVillager, player, OptimizationType.WORKSTATION, event.isAsynchronous());
|
||||
VillagerUnoptimizeEvent unOptimizeEvent = new VillagerUnoptimizeEvent(
|
||||
closestOptimizedVillager,
|
||||
player,
|
||||
OptimizationType.WORKSTATION,
|
||||
event.isAsynchronous()
|
||||
);
|
||||
|
||||
if (!unOptimizeEvent.callEvent()) return;
|
||||
|
||||
closestOptimizedVillager.setOptimizationType(OptimizationType.NONE);
|
||||
@ -215,16 +225,14 @@ public class OptimizeByWorkstation implements VillagerOptimizerModule, Listener
|
||||
.matchLiteral("%workstation%")
|
||||
.replacement(broken.getType().toString().toLowerCase())
|
||||
.build();
|
||||
VillagerOptimizer.getLang(player.locale()).workstation_unoptimize_success.forEach(line -> player.sendMessage(line
|
||||
.replaceText(vilProfession)
|
||||
.replaceText(brokenWorkstation)
|
||||
));
|
||||
VillagerOptimizer.getLang(player.locale()).workstation_unoptimize_success
|
||||
.forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(vilProfession).replaceText(brokenWorkstation)));
|
||||
}
|
||||
|
||||
if (log_enabled) {
|
||||
VillagerOptimizer.getLog().info(Component.text(player.getName() +
|
||||
" unoptimized villager by workstation (" + broken.getType().toString().toLowerCase() + ") at " +
|
||||
CommonUtil.formatLocation(closestOptimizedVillager.villager().getLocation())).color(VillagerOptimizer.plugin_style.color()));
|
||||
CommonUtil.formatLocation(closestOptimizedVillager.villager().getLocation())).color(VillagerOptimizer.STYLE.color()));
|
||||
}
|
||||
}
|
||||
}
|
@ -12,9 +12,9 @@ public class CommonUtil {
|
||||
public static @NotNull String formatDuration(Duration duration) {
|
||||
if (duration.isNegative()) duration = duration.negated();
|
||||
|
||||
final int seconds = duration.toSecondsPart();
|
||||
final int minutes = duration.toMinutesPart();
|
||||
final int hours = duration.toHoursPart();
|
||||
final int seconds = (int) (duration.getSeconds() % 60);
|
||||
final int minutes = (int) (duration.toMinutes() % 60);
|
||||
final int hours = (int) (duration.toHours() % 24);
|
||||
|
||||
if (hours > 0) {
|
||||
return String.format("%02dh %02dm %02ds", hours, minutes, seconds);
|
||||
@ -49,21 +49,35 @@ public class CommonUtil {
|
||||
}
|
||||
|
||||
public static Villager.Profession getWorkstationProfession(@NotNull Material workstation) {
|
||||
return switch (workstation) {
|
||||
case BARREL -> Villager.Profession.FISHERMAN;
|
||||
case CARTOGRAPHY_TABLE -> Villager.Profession.CARTOGRAPHER;
|
||||
case SMOKER -> Villager.Profession.BUTCHER;
|
||||
case SMITHING_TABLE -> Villager.Profession.TOOLSMITH;
|
||||
case GRINDSTONE -> Villager.Profession.WEAPONSMITH;
|
||||
case BLAST_FURNACE -> Villager.Profession.ARMORER;
|
||||
case CAULDRON -> Villager.Profession.LEATHERWORKER;
|
||||
case BREWING_STAND -> Villager.Profession.CLERIC;
|
||||
case COMPOSTER -> Villager.Profession.FARMER;
|
||||
case FLETCHING_TABLE -> Villager.Profession.FLETCHER;
|
||||
case LOOM -> Villager.Profession.SHEPHERD;
|
||||
case LECTERN -> Villager.Profession.LIBRARIAN;
|
||||
case STONECUTTER -> Villager.Profession.MASON;
|
||||
default -> Villager.Profession.NONE;
|
||||
};
|
||||
switch (workstation) {
|
||||
case BARREL:
|
||||
return Villager.Profession.FISHERMAN;
|
||||
case CARTOGRAPHY_TABLE:
|
||||
return Villager.Profession.CARTOGRAPHER;
|
||||
case SMOKER:
|
||||
return Villager.Profession.BUTCHER;
|
||||
case SMITHING_TABLE:
|
||||
return Villager.Profession.TOOLSMITH;
|
||||
case GRINDSTONE:
|
||||
return Villager.Profession.WEAPONSMITH;
|
||||
case BLAST_FURNACE:
|
||||
return Villager.Profession.ARMORER;
|
||||
case CAULDRON:
|
||||
return Villager.Profession.LEATHERWORKER;
|
||||
case BREWING_STAND:
|
||||
return Villager.Profession.CLERIC;
|
||||
case COMPOSTER:
|
||||
return Villager.Profession.FARMER;
|
||||
case FLETCHING_TABLE:
|
||||
return Villager.Profession.FLETCHER;
|
||||
case LOOM:
|
||||
return Villager.Profession.SHEPHERD;
|
||||
case LECTERN:
|
||||
return Villager.Profession.LIBRARIAN;
|
||||
case STONECUTTER:
|
||||
return Villager.Profession.MASON;
|
||||
default:
|
||||
return Villager.Profession.NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
package me.xginko.villageroptimizer.utils;
|
||||
|
||||
import me.xginko.villageroptimizer.VillagerOptimizer;
|
||||
import net.kyori.adventure.identity.Identity;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class KyoriUtil {
|
||||
|
||||
public static void sendMessage(CommandSender sender, Component message) {
|
||||
VillagerOptimizer.getAudiences().sender(sender).sendMessage(message);
|
||||
}
|
||||
|
||||
public static void sendActionBar(CommandSender sender, Component message) {
|
||||
VillagerOptimizer.getAudiences().sender(sender).sendActionBar(message);
|
||||
}
|
||||
|
||||
public static Locale getLocale(Player player) {
|
||||
return VillagerOptimizer.getAudiences().player(player).pointers().getOrDefault(Identity.LOCALE, Locale.US);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user