Merge remote-tracking branch 'origin/develop-chatReply' into develop-chatReply
This commit is contained in:
commit
d8259b79ae
@ -26,6 +26,7 @@ dependencies {
|
|||||||
compileOnly 'org.geysermc.floodgate:api:2.2.2-SNAPSHOT'
|
compileOnly 'org.geysermc.floodgate:api:2.2.2-SNAPSHOT'
|
||||||
implementation 'org.apache.httpcomponents:httpclient:4.5.14'
|
implementation 'org.apache.httpcomponents:httpclient:4.5.14'
|
||||||
implementation 'com.sparkjava:spark-core:2.9.4'
|
implementation 'com.sparkjava:spark-core:2.9.4'
|
||||||
|
implementation 'org.reflections:reflections:0.10.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
def targetJavaVersion = 21
|
def targetJavaVersion = 21
|
||||||
|
@ -2,39 +2,16 @@ package eu.mhsl.craftattack.spawn;
|
|||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.api.HttpServer;
|
import eu.mhsl.craftattack.spawn.api.HttpServer;
|
||||||
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.antiSignEdit.AntiSignEdit;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarker;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.autoShulker.AutoShulker;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.chatMention.ChatMention;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.chatMessages.ChatMessages;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.customAdvancements.CustomAdvancements;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.debug.Debug;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.displayName.DisplayName;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.event.Event;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.fleischerchest.Fleischerchest;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.help.Help;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.hotbarRefill.HotbarRefill;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.kick.Kick;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.outlawed.Outlawed;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.panicBan.PanicBan;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.playerlimit.PlayerLimit;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.portableCrafting.PortableCrafting;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.privateMessage.PrivateMessage;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.projectStart.ProjectStart;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.report.Report;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.restart.Restart;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.tablist.Tablist;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.titleClear.TitleClear;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.whitelist.Whitelist;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.worldmuseum.WorldMuseum;
|
|
||||||
import eu.mhsl.craftattack.spawn.config.Configuration;
|
import eu.mhsl.craftattack.spawn.config.Configuration;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
import org.reflections.Reflections;
|
||||||
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public final class Main extends JavaPlugin {
|
public final class Main extends JavaPlugin {
|
||||||
@ -49,49 +26,46 @@ public final class Main extends JavaPlugin {
|
|||||||
instance = this;
|
instance = this;
|
||||||
logger = instance().getLogger();
|
logger = instance().getLogger();
|
||||||
saveDefaultConfig();
|
saveDefaultConfig();
|
||||||
Configuration.readConfig();
|
try {
|
||||||
|
this.wrappedEnable();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Main.logger().log(Level.SEVERE, "Error while initializing Spawn plugin, shutting down!", e);
|
||||||
|
Bukkit.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
appliances = List.of(
|
private void wrappedEnable() {
|
||||||
new AdminMarker(),
|
Configuration.readConfig();
|
||||||
new WorldMuseum(),
|
List<String> disabledAppliances = Configuration.pluginConfig.getStringList("disabledAppliances");
|
||||||
new TitleClear(),
|
|
||||||
new ProjectStart(),
|
|
||||||
new Tablist(),
|
|
||||||
new ChatMessages(),
|
|
||||||
new Report(),
|
|
||||||
new Event(),
|
|
||||||
new Help(),
|
|
||||||
new PlayerLimit(),
|
|
||||||
new Whitelist(),
|
|
||||||
new Restart(),
|
|
||||||
new Kick(),
|
|
||||||
new PanicBan(),
|
|
||||||
new Outlawed(),
|
|
||||||
new DisplayName(),
|
|
||||||
new Debug(),
|
|
||||||
new Fleischerchest(),
|
|
||||||
new CustomAdvancements(),
|
|
||||||
new Settings(),
|
|
||||||
new PortableCrafting(),
|
|
||||||
new AutoShulker(),
|
|
||||||
new AntiSignEdit(),
|
|
||||||
new HotbarRefill(),
|
|
||||||
new ChatMention(),
|
|
||||||
new PrivateMessage()
|
|
||||||
);
|
|
||||||
|
|
||||||
Main.logger.info("Loading appliances...");
|
Main.logger.info("Loading appliances...");
|
||||||
appliances.forEach(appliance -> {
|
Reflections reflections = new Reflections(this.getClass().getPackageName());
|
||||||
Main.logger().info("Enabling " + appliance.getClass().getSimpleName());
|
Set<Class<? extends Appliance>> applianceClasses = reflections.getSubTypesOf(Appliance.class);
|
||||||
|
|
||||||
|
this.appliances = applianceClasses.stream()
|
||||||
|
.filter(applianceClass -> !disabledAppliances.contains(applianceClass.getSimpleName()))
|
||||||
|
.map(applianceClass -> {
|
||||||
|
try {
|
||||||
|
return (Appliance) applianceClass.getDeclaredConstructor().newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(String.format("Failed to create instance of '%s'", applianceClass.getName()), e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.toList();
|
||||||
|
Main.logger().info(String.format("Loaded %d appliances!", appliances.size()));
|
||||||
|
|
||||||
|
Main.logger().info("Initializing appliances...");
|
||||||
|
this.appliances.forEach(appliance -> {
|
||||||
appliance.onEnable();
|
appliance.onEnable();
|
||||||
appliance.initialize(this);
|
appliance.initialize(this);
|
||||||
});
|
});
|
||||||
Main.logger().info("Loaded " + appliances.size() + " appliances!");
|
Main.logger().info(String.format("Initialized %d appliances!", appliances.size()));
|
||||||
|
|
||||||
Main.logger().info("Starting HTTP API");
|
Main.logger().info("Starting HTTP API...");
|
||||||
this.httpApi = new HttpServer();
|
this.httpApi = new HttpServer();
|
||||||
|
|
||||||
getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
|
getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
|
||||||
|
Main.logger().info("Startup complete!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -42,7 +42,7 @@ public abstract class Appliance {
|
|||||||
* @return List of listeners
|
* @return List of listeners
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<Listener> eventHandlers() {
|
protected List<Listener> listeners() {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,8 @@ public abstract class Appliance {
|
|||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public ConfigurationSection localConfig() {
|
public ConfigurationSection localConfig() {
|
||||||
return Optional.ofNullable(Configuration.cfg.getConfigurationSection(localConfigPath)).orElse(Configuration.cfg);
|
return Optional.ofNullable(Configuration.cfg.getConfigurationSection(localConfigPath))
|
||||||
|
.orElseGet(() -> Configuration.cfg.createSection(localConfigPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
@ -82,7 +83,7 @@ public abstract class Appliance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void initialize(@NotNull JavaPlugin plugin) {
|
public void initialize(@NotNull JavaPlugin plugin) {
|
||||||
this.listeners = eventHandlers();
|
this.listeners = listeners();
|
||||||
this.commands = commands();
|
this.commands = commands();
|
||||||
|
|
||||||
listeners.forEach(listener -> Bukkit.getPluginManager().registerEvents(listener, plugin));
|
listeners.forEach(listener -> Bukkit.getPluginManager().registerEvents(listener, plugin));
|
||||||
@ -93,7 +94,7 @@ public abstract class Appliance {
|
|||||||
listeners.forEach(HandlerList::unregisterAll);
|
listeners.forEach(HandlerList::unregisterAll);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends Appliance> T queryAppliance(Class<T> clazz) {
|
protected static <T extends Appliance> T queryAppliance(Class<T> clazz) {
|
||||||
return Main.instance().getAppliance(clazz);
|
return Main.instance().getAppliance(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import java.util.Optional;
|
|||||||
/**
|
/**
|
||||||
* Utility class which enables command name definition over a constructor.
|
* Utility class which enables command name definition over a constructor.
|
||||||
*/
|
*/
|
||||||
public abstract class ApplianceCommand<T extends Appliance> extends ApplianceSupplier<T> implements TabCompleter, CommandExecutor {
|
public abstract class ApplianceCommand<T extends Appliance> extends CachedApplianceSupplier<T> implements TabCompleter, CommandExecutor {
|
||||||
public String commandName;
|
public String commandName;
|
||||||
protected Component errorMessage = Component.text("Fehler: ").color(NamedTextColor.RED);
|
protected Component errorMessage = Component.text("Fehler: ").color(NamedTextColor.RED);
|
||||||
|
|
||||||
|
@ -8,6 +8,6 @@ import org.bukkit.event.Listener;
|
|||||||
*
|
*
|
||||||
* @param <T> the type of your appliance
|
* @param <T> the type of your appliance
|
||||||
*/
|
*/
|
||||||
public abstract class ApplianceListener<T extends Appliance> extends ApplianceSupplier<T> implements Listener {
|
public abstract class ApplianceListener<T extends Appliance> extends CachedApplianceSupplier<T> implements Listener {
|
||||||
|
|
||||||
}
|
}
|
@ -2,10 +2,10 @@ package eu.mhsl.craftattack.spawn.appliance;
|
|||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.Main;
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
|
|
||||||
public class ApplianceSupplier<T extends Appliance> implements IApplianceSupplier<T> {
|
public class CachedApplianceSupplier<T extends Appliance> implements IApplianceSupplier<T> {
|
||||||
private final T appliance;
|
private final T appliance;
|
||||||
|
|
||||||
public ApplianceSupplier() {
|
public CachedApplianceSupplier() {
|
||||||
this.appliance = Main.instance().getAppliance(Main.getApplianceType(getClass()));
|
this.appliance = Main.instance().getAppliance(Main.getApplianceType(getClass()));
|
||||||
}
|
}
|
||||||
|
|
@ -18,7 +18,7 @@ public class AdminMarker extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<Listener> eventHandlers() {
|
protected List<Listener> listeners() {
|
||||||
return List.of(new AdminMarkerListener());
|
return List.of(new AdminMarkerListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package eu.mhsl.craftattack.spawn.appliances.antiSignEdit;
|
|||||||
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.SelectSetting;
|
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.SelectSetting;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.settings.SignEditSetting;
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||||
@ -15,6 +14,11 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class AntiSignEdit extends Appliance {
|
public class AntiSignEdit extends Appliance {
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
Settings.instance().declareSetting(SignEditSetting.class);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean preventSignEdit(Player p, SignSide sign) {
|
public boolean preventSignEdit(Player p, SignSide sign) {
|
||||||
SelectSetting.Options.Option setting = Settings.instance().getSetting(p, Settings.Key.SignEdit, SelectSetting.Options.Option.class);
|
SelectSetting.Options.Option setting = Settings.instance().getSetting(p, Settings.Key.SignEdit, SelectSetting.Options.Option.class);
|
||||||
if(setting.is(SignEditSetting.editable)) return false;
|
if(setting.is(SignEditSetting.editable)) return false;
|
||||||
@ -37,7 +41,7 @@ public class AntiSignEdit extends Appliance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected @NotNull List<Listener> eventHandlers() {
|
protected @NotNull List<Listener> listeners() {
|
||||||
return List.of(new OnSignEditListener());
|
return List.of(new OnSignEditListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package eu.mhsl.craftattack.spawn.appliances.settings.settings;
|
package eu.mhsl.craftattack.spawn.appliances.antiSignEdit;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
@ -1,6 +1,7 @@
|
|||||||
package eu.mhsl.craftattack.spawn.appliances.autoShulker;
|
package eu.mhsl.craftattack.spawn.appliances.autoShulker;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
@ -16,6 +17,11 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class AutoShulker extends Appliance {
|
public class AutoShulker extends Appliance {
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
Settings.instance().declareSetting(AutoShulkerSetting.class);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean tryAutoShulker(Player p, Item item) {
|
public boolean tryAutoShulker(Player p, Item item) {
|
||||||
ItemStack itemStack = item.getItemStack();
|
ItemStack itemStack = item.getItemStack();
|
||||||
ItemStack offhandStack = p.getInventory().getItemInOffHand();
|
ItemStack offhandStack = p.getInventory().getItemInOffHand();
|
||||||
@ -40,7 +46,7 @@ public class AutoShulker extends Appliance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected @NotNull List<Listener> eventHandlers() {
|
protected @NotNull List<Listener> listeners() {
|
||||||
return List.of(new ItemPickupListener());
|
return List.of(new ItemPickupListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package eu.mhsl.craftattack.spawn.appliances.settings.settings;
|
package eu.mhsl.craftattack.spawn.appliances.autoShulker;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
@ -3,7 +3,6 @@ package eu.mhsl.craftattack.spawn.appliances.autoShulker;
|
|||||||
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.SelectSetting;
|
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.SelectSetting;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.settings.AutoShulkerSetting;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.entity.EntityPickupItemEvent;
|
import org.bukkit.event.entity.EntityPickupItemEvent;
|
||||||
|
@ -3,7 +3,6 @@ package eu.mhsl.craftattack.spawn.appliances.chatMention;
|
|||||||
import eu.mhsl.craftattack.spawn.Main;
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.settings.ChatMentionSetting;
|
|
||||||
import net.kyori.adventure.sound.Sound;
|
import net.kyori.adventure.sound.Sound;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
@ -56,11 +55,12 @@ public class ChatMention extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
|
Settings.instance().declareSetting(ChatMentionSetting.class);
|
||||||
refreshPlayers();
|
refreshPlayers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected @NotNull List<Listener> eventHandlers() {
|
protected @NotNull List<Listener> listeners() {
|
||||||
return List.of(new ChatMentionListener());
|
return List.of(new ChatMentionListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import eu.mhsl.craftattack.spawn.Main;
|
|||||||
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.chatMessages.ChatMessages;
|
import eu.mhsl.craftattack.spawn.appliances.chatMessages.ChatMessages;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.settings.ChatMentionSetting;
|
import eu.mhsl.craftattack.spawn.util.text.ComponentUtil;
|
||||||
import io.papermc.paper.event.player.AsyncChatDecorateEvent;
|
import io.papermc.paper.event.player.AsyncChatDecorateEvent;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
@ -42,7 +42,7 @@ public class ChatMentionListener extends ApplianceListener<ChatMention> {
|
|||||||
return Component.text(word);
|
return Component.text(word);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.reduce((a, b) -> a.append(Component.text(" ")).append(b))
|
.reduce(ComponentUtil::appendWithSpace)
|
||||||
.orElseThrow();
|
.orElseThrow();
|
||||||
|
|
||||||
getAppliance().notifyPlayers(mentioned);
|
getAppliance().notifyPlayers(mentioned);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package eu.mhsl.craftattack.spawn.appliances.settings.settings;
|
package eu.mhsl.craftattack.spawn.appliances.chatMention;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
||||||
@ -9,7 +9,7 @@ import org.bukkit.Material;
|
|||||||
public class ChatMentionSetting extends MultiBoolSetting<ChatMentionSetting.ChatMentionConfig> implements CategorizedSetting {
|
public class ChatMentionSetting extends MultiBoolSetting<ChatMentionSetting.ChatMentionConfig> implements CategorizedSetting {
|
||||||
@Override
|
@Override
|
||||||
public SettingCategory category() {
|
public SettingCategory category() {
|
||||||
return SettingCategory.Chat;
|
return SettingCategory.Visuals;
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ChatMentionConfig(
|
public record ChatMentionConfig(
|
@ -1,6 +1,7 @@
|
|||||||
package eu.mhsl.craftattack.spawn.appliances.chatMessages;
|
package eu.mhsl.craftattack.spawn.appliances.chatMessages;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.event.ClickEvent;
|
import net.kyori.adventure.text.event.ClickEvent;
|
||||||
import net.kyori.adventure.text.event.HoverEvent;
|
import net.kyori.adventure.text.event.HoverEvent;
|
||||||
@ -12,6 +13,11 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ChatMessages extends Appliance {
|
public class ChatMessages extends Appliance {
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
Settings.instance().declareSetting(ShowJoinAndLeaveMessagesSetting.class);
|
||||||
|
}
|
||||||
|
|
||||||
public Component getReportablePlayerName(Player player) {
|
public Component getReportablePlayerName(Player player) {
|
||||||
return addReportActions(player.displayName(), player.getName());
|
return addReportActions(player.displayName(), player.getName());
|
||||||
}
|
}
|
||||||
@ -24,7 +30,7 @@ public class ChatMessages extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<Listener> eventHandlers() {
|
protected List<Listener> listeners() {
|
||||||
return List.of(new ChatMessagesListener());
|
return List.of(new ChatMessagesListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package eu.mhsl.craftattack.spawn.appliances.settings.settings;
|
package eu.mhsl.craftattack.spawn.appliances.chatMessages;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
||||||
@ -33,6 +33,6 @@ public class ShowJoinAndLeaveMessagesSetting extends BoolSetting implements Cate
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SettingCategory category() {
|
public SettingCategory category() {
|
||||||
return SettingCategory.Chat;
|
return SettingCategory.Visuals;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,7 +17,7 @@ public class CustomAdvancements extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<Listener> eventHandlers() {
|
protected List<Listener> listeners() {
|
||||||
return List.of(new CustomAdvancementsDamageEntityListener());
|
return List.of(new CustomAdvancementsDamageEntityListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package eu.mhsl.craftattack.spawn.appliances.customAdvancements;
|
package eu.mhsl.craftattack.spawn.appliances.customAdvancements;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||||
@ -9,12 +9,11 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
|||||||
public class CustomAdvancementsDamageEntityListener extends ApplianceListener<CustomAdvancements> {
|
public class CustomAdvancementsDamageEntityListener extends ApplianceListener<CustomAdvancements> {
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onEntityDamageEntity(EntityDamageByEntityEvent event) {
|
public void onEntityDamageEntity(EntityDamageByEntityEvent event) {
|
||||||
Entity damaged = event.getEntity();
|
if(!(event.getEntity() instanceof Player damaged)) return;
|
||||||
if(!(damaged instanceof Player)) return;
|
if(!(event.getDamager() instanceof Player damager)) return;
|
||||||
Entity damager = event.getDamager();
|
if(!damager.getInventory().getItemInMainHand().getType().equals(Material.AIR)) return;
|
||||||
if(!(damager instanceof Player)) return;
|
if(!damaged.hasPermission("admin")) return;
|
||||||
if(damaged.hasPermission("admin")) {
|
|
||||||
getAppliance().grantAdvancement("search_trouble", (Player) damager);
|
getAppliance().grantAdvancement("search_trouble", damager);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package eu.mhsl.craftattack.spawn.appliances.displayName;
|
package eu.mhsl.craftattack.spawn.appliances.displayName;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarker;
|
import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarker;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarkerListener;
|
import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarkerListener;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.outlawed.Outlawed;
|
import eu.mhsl.craftattack.spawn.appliances.outlawed.Outlawed;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.yearRank.YearRank;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.ComponentBuilder;
|
import net.kyori.adventure.text.ComponentBuilder;
|
||||||
import net.kyori.adventure.text.TextComponent;
|
import net.kyori.adventure.text.TextComponent;
|
||||||
@ -14,19 +16,22 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
public class DisplayName extends Appliance {
|
public class DisplayName extends Appliance {
|
||||||
public void update(Player player) {
|
public void update(Player player) {
|
||||||
TextColor playerColor = queryAppliance(AdminMarker.class).getPlayerColor(player);
|
TextColor playerColor = queryAppliance(AdminMarker.class).getPlayerColor(player);
|
||||||
List<Supplier<Component>> prefixes = List.of(
|
List<Supplier<Component>> prefixes = List.of(
|
||||||
() -> queryAppliance(Outlawed.class).getNamePrefix(player)
|
() -> queryAppliance(Outlawed.class).getNamePrefix(player),
|
||||||
|
() -> queryAppliance(YearRank.class).getNamePrefix(player)
|
||||||
);
|
);
|
||||||
|
|
||||||
ComponentBuilder<TextComponent, TextComponent.Builder> playerName = Component.text();
|
ComponentBuilder<TextComponent, TextComponent.Builder> playerName = Component.text();
|
||||||
prefixes.forEach(supplier -> {
|
prefixes.forEach(supplier -> {
|
||||||
Component prefix = supplier.get();
|
Component prefix = supplier.get();
|
||||||
if(prefix == null) return;
|
if(prefix == null) return;
|
||||||
playerName.append(prefix).append(Component.text(" "));
|
playerName.append(prefix).append(
|
||||||
|
Component.text(" ").hoverEvent(Component.empty().asHoverEvent()));
|
||||||
});
|
});
|
||||||
|
|
||||||
playerName.append(Component.text(player.getName(), playerColor));
|
playerName.append(Component.text(player.getName(), playerColor));
|
||||||
@ -41,14 +46,14 @@ public class DisplayName extends Appliance {
|
|||||||
player.playerListName(component);
|
player.playerListName(component);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
//TODO this throws often exceptions, but still works, don't know why
|
//TODO this throws often exceptions, but still works, don't know why
|
||||||
//Main.instance().getLogger().log(Level.SEVERE, e, e::getMessage);
|
Main.instance().getLogger().log(Level.SEVERE, e, e::getMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<Listener> eventHandlers() {
|
protected List<Listener> listeners() {
|
||||||
return List.of(new AdminMarkerListener());
|
return List.of(new AdminMarkerListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.doubeDoor;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.block.data.type.Door;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DoubleDoor extends Appliance {
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
Settings.instance().declareSetting(DoubleDoorSetting.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openNextDoor(Block block) {
|
||||||
|
BlockData clickedData = block.getBlockData();
|
||||||
|
if (!(clickedData instanceof Door clickedDoor)) return;
|
||||||
|
|
||||||
|
BlockFace neighborFace = getNeighborFace(clickedDoor.getFacing(), clickedDoor.getHinge());
|
||||||
|
Block neighbourBlock = block.getRelative(neighborFace);
|
||||||
|
BlockData neighbourData = neighbourBlock.getBlockData();
|
||||||
|
|
||||||
|
if(!(neighbourData instanceof Door neighbourDoor)) return;
|
||||||
|
if(!(neighbourDoor.getFacing() == clickedDoor.getFacing())) return;
|
||||||
|
if(neighbourDoor.getHinge() == clickedDoor.getHinge()) return;
|
||||||
|
|
||||||
|
neighbourDoor.setOpen(!clickedDoor.isOpen());
|
||||||
|
neighbourBlock.setBlockData(neighbourDoor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private @NotNull BlockFace getNeighborFace(BlockFace face, Door.Hinge hinge) {
|
||||||
|
return switch(face) {
|
||||||
|
case EAST -> (hinge == Door.Hinge.RIGHT) ? BlockFace.NORTH : BlockFace.SOUTH;
|
||||||
|
case WEST -> (hinge == Door.Hinge.RIGHT) ? BlockFace.SOUTH : BlockFace.NORTH;
|
||||||
|
case SOUTH -> (hinge == Door.Hinge.RIGHT) ? BlockFace.EAST : BlockFace.WEST;
|
||||||
|
case NORTH -> (hinge == Door.Hinge.RIGHT) ? BlockFace.WEST : BlockFace.EAST;
|
||||||
|
default -> throw new IllegalStateException(String.format("BlockFace '%s' of clicked door is not valid!", face));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull List<Listener> listeners() {
|
||||||
|
return List.of(new OnDoorInteractListener());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.doubeDoor;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.BoolSetting;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
|
||||||
|
public class DoubleDoorSetting extends BoolSetting implements CategorizedSetting {
|
||||||
|
public DoubleDoorSetting() {
|
||||||
|
super(Settings.Key.DoubleDoors);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String title() {
|
||||||
|
return "Automatische Doppeltüren";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String description() {
|
||||||
|
return "Öffnet und schließt die zweite Hälfte einer Doppeltür automatisch";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Material icon() {
|
||||||
|
return Material.OAK_DOOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Boolean defaultValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SettingCategory category() {
|
||||||
|
return SettingCategory.Gameplay;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.doubeDoor;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class OnDoorInteractListener extends ApplianceListener<DoubleDoor> {
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||||
|
if(!event.hasBlock()) return;
|
||||||
|
if(!Objects.equals(event.getHand(), EquipmentSlot.HAND)) return;
|
||||||
|
if(!event.getAction().equals(Action.RIGHT_CLICK_BLOCK)) return;
|
||||||
|
if(event.getPlayer().isSneaking()) return;
|
||||||
|
Block clickedBlock = event.getClickedBlock();
|
||||||
|
if(clickedBlock == null) return;
|
||||||
|
if(clickedBlock.getType().equals(Material.IRON_DOOR)) return;
|
||||||
|
if(!Settings.instance().getSetting(event.getPlayer(), Settings.Key.DoubleDoors, Boolean.class)) return;
|
||||||
|
getAppliance().openNextDoor(clickedBlock);
|
||||||
|
}
|
||||||
|
}
|
@ -201,17 +201,15 @@ public class Event extends Appliance {
|
|||||||
public void advertise() {
|
public void advertise() {
|
||||||
advertiseCountdown.cancelIfRunning();
|
advertiseCountdown.cancelIfRunning();
|
||||||
this.advertiseStatus = AdvertisementStatus.ADVERTISED;
|
this.advertiseStatus = AdvertisementStatus.ADVERTISED;
|
||||||
IteratorUtil.onlinePlayers(player -> {
|
IteratorUtil.onlinePlayers(player -> player.sendMessage(
|
||||||
player.sendMessage(
|
Component.text()
|
||||||
Component.text()
|
.append(Component.text("-".repeat(10), NamedTextColor.GRAY)).appendNewline()
|
||||||
.append(Component.text("-".repeat(10), NamedTextColor.GRAY)).appendNewline()
|
.append(Component.text("Ein Event wurde gestartet!", NamedTextColor.GOLD)).appendNewline()
|
||||||
.append(Component.text("Ein Event wurde gestartet!", NamedTextColor.GOLD)).appendNewline()
|
.append(Component.text("Nutze "))
|
||||||
.append(Component.text("Nutze "))
|
.append(Component.text("/event", NamedTextColor.AQUA))
|
||||||
.append(Component.text("/event", NamedTextColor.AQUA))
|
.append(Component.text(", um dem Event beizutreten!")).appendNewline()
|
||||||
.append(Component.text(", um dem Event beizutreten!")).appendNewline()
|
.append(Component.text("-".repeat(10), NamedTextColor.GRAY)).appendNewline()
|
||||||
.append(Component.text("-".repeat(10), NamedTextColor.GRAY)).appendNewline()
|
));
|
||||||
);
|
|
||||||
});
|
|
||||||
advertiseCountdown.start();
|
advertiseCountdown.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,7 +235,7 @@ public class Event extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<Listener> eventHandlers() {
|
protected List<Listener> listeners() {
|
||||||
return List.of(
|
return List.of(
|
||||||
new ApplyPendingRewardsListener(),
|
new ApplyPendingRewardsListener(),
|
||||||
new PlayerInteractAtEntityEventListener(this.villager.getUniqueId(), playerInteractAtEntityEvent -> joinEvent(playerInteractAtEntityEvent.getPlayer())),
|
new PlayerInteractAtEntityEventListener(this.villager.getUniqueId(), playerInteractAtEntityEvent -> joinEvent(playerInteractAtEntityEvent.getPlayer())),
|
||||||
|
@ -19,7 +19,7 @@ public class Fleischerchest extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<Listener> eventHandlers() {
|
protected List<Listener> listeners() {
|
||||||
return List.of(new FleischerchestCraftItemListener());
|
return List.of(new FleischerchestCraftItemListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.glowingBerries;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
|
import net.kyori.adventure.sound.Sound;
|
||||||
|
import net.kyori.adventure.util.Ticks;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.potion.PotionEffect;
|
||||||
|
import org.bukkit.potion.PotionEffectType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GlowingBerries extends Appliance {
|
||||||
|
private static final PotionEffect glowEffect = new PotionEffect(
|
||||||
|
PotionEffectType.GLOWING,
|
||||||
|
Ticks.TICKS_PER_SECOND * 15,
|
||||||
|
1,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
public void letPlayerGlow(Player player) {
|
||||||
|
player.addPotionEffect(glowEffect);
|
||||||
|
Sound sound = Sound.sound(org.bukkit.Sound.BLOCK_AMETHYST_BLOCK_CHIME.key(), Sound.Source.PLAYER, 1f, 1f);
|
||||||
|
player.stopSound(sound);
|
||||||
|
player.playSound(sound, Sound.Emitter.self());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull List<Listener> listeners() {
|
||||||
|
return List.of(new OnBerryEaten());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.glowingBerries;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.player.PlayerItemConsumeEvent;
|
||||||
|
|
||||||
|
public class OnBerryEaten extends ApplianceListener<GlowingBerries> {
|
||||||
|
@EventHandler
|
||||||
|
public void onEat(PlayerItemConsumeEvent event) {
|
||||||
|
if(event.getItem().getType().equals(Material.GLOW_BERRIES)) getAppliance().letPlayerGlow(event.getPlayer());
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ package eu.mhsl.craftattack.spawn.appliances.hotbarRefill;
|
|||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.Main;
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
@ -16,6 +17,11 @@ import java.util.List;
|
|||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
public class HotbarRefill extends Appliance {
|
public class HotbarRefill extends Appliance {
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
Settings.instance().declareSetting(HotbarRefillSetting.class);
|
||||||
|
}
|
||||||
|
|
||||||
public void handleHotbarChange(Player player, ItemStack item) {
|
public void handleHotbarChange(Player player, ItemStack item) {
|
||||||
if(player.getGameMode().equals(GameMode.CREATIVE)) return;
|
if(player.getGameMode().equals(GameMode.CREATIVE)) return;
|
||||||
if(item.getAmount() != 1) return;
|
if(item.getAmount() != 1) return;
|
||||||
@ -46,7 +52,7 @@ public class HotbarRefill extends Appliance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected @NotNull List<Listener> eventHandlers() {
|
protected @NotNull List<Listener> listeners() {
|
||||||
return List.of(new ItemRefillListener());
|
return List.of(new HotbarRefillListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package eu.mhsl.craftattack.spawn.appliances.hotbarRefill;
|
|||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.settings.HotbarReplaceSetting;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.block.BlockPlaceEvent;
|
import org.bukkit.event.block.BlockPlaceEvent;
|
||||||
@ -10,12 +9,12 @@ import org.bukkit.event.player.PlayerItemBreakEvent;
|
|||||||
import org.bukkit.event.player.PlayerItemConsumeEvent;
|
import org.bukkit.event.player.PlayerItemConsumeEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
public class ItemRefillListener extends ApplianceListener<HotbarRefill> {
|
public class HotbarRefillListener extends ApplianceListener<HotbarRefill> {
|
||||||
private HotbarReplaceSetting.HotbarReplaceConfig getPlayerSetting(Player player) {
|
private HotbarRefillSetting.HotbarReplaceConfig getPlayerSetting(Player player) {
|
||||||
return Settings.instance().getSetting(
|
return Settings.instance().getSetting(
|
||||||
player,
|
player,
|
||||||
Settings.Key.HotbarReplacer,
|
Settings.Key.HotbarReplacer,
|
||||||
HotbarReplaceSetting.HotbarReplaceConfig.class
|
HotbarRefillSetting.HotbarReplaceConfig.class
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package eu.mhsl.craftattack.spawn.appliances.settings.settings;
|
package eu.mhsl.craftattack.spawn.appliances.hotbarRefill;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
||||||
@ -6,7 +6,7 @@ import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
|||||||
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.MultiBoolSetting;
|
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.MultiBoolSetting;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
|
||||||
public class HotbarReplaceSetting extends MultiBoolSetting<HotbarReplaceSetting.HotbarReplaceConfig> implements CategorizedSetting {
|
public class HotbarRefillSetting extends MultiBoolSetting<HotbarRefillSetting.HotbarReplaceConfig> implements CategorizedSetting {
|
||||||
@Override
|
@Override
|
||||||
public SettingCategory category() {
|
public SettingCategory category() {
|
||||||
return SettingCategory.Gameplay;
|
return SettingCategory.Gameplay;
|
||||||
@ -18,7 +18,7 @@ public class HotbarReplaceSetting extends MultiBoolSetting<HotbarReplaceSetting.
|
|||||||
@DisplayName("Essen") boolean onConsumable
|
@DisplayName("Essen") boolean onConsumable
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public HotbarReplaceSetting() {
|
public HotbarRefillSetting() {
|
||||||
super(Settings.Key.HotbarReplacer);
|
super(Settings.Key.HotbarReplacer);
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.knockDoor;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.SelectSetting;
|
||||||
|
import org.bukkit.*;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.metadata.FixedMetadataValue;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class KnockDoor extends Appliance {
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
Settings.instance().declareSetting(KnockDoorSetting.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void knockAtDoor(Player knockingPlayer, Block knockedBlock) {
|
||||||
|
SelectSetting.Options.Option setting = Settings.instance().getSetting(knockingPlayer, Settings.Key.KnockDoors, SelectSetting.Options.Option.class);
|
||||||
|
if(setting.is(KnockDoorSetting.disabled)) return;
|
||||||
|
|
||||||
|
if(setting.is(KnockDoorSetting.knockSingleTime)) {
|
||||||
|
playSound(knockedBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(setting.is(KnockDoorSetting.knockThreeTimes)) {
|
||||||
|
String metadataKey = new NamespacedKey(Main.instance(), KnockDoor.class.getName()).getNamespace();
|
||||||
|
if(knockingPlayer.hasMetadata(metadataKey)) return;
|
||||||
|
knockingPlayer.setMetadata(metadataKey, new FixedMetadataValue(Main.instance(), 0));
|
||||||
|
|
||||||
|
new BukkitRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
int timesKnocked = knockingPlayer.getMetadata(metadataKey).getFirst().asInt();
|
||||||
|
if(timesKnocked >= 3) {
|
||||||
|
knockingPlayer.removeMetadata(metadataKey, Main.instance());
|
||||||
|
cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
playSound(knockedBlock);
|
||||||
|
knockingPlayer.setMetadata(metadataKey, new FixedMetadataValue(Main.instance(), timesKnocked + 1));
|
||||||
|
}
|
||||||
|
}.runTaskTimer(Main.instance(), 0, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void playSound(Block knockedBlock) {
|
||||||
|
Location knockLocation = knockedBlock.getLocation();
|
||||||
|
Sound sound = knockedBlock.getType() == Material.IRON_DOOR
|
||||||
|
? Sound.ENTITY_ZOMBIE_ATTACK_IRON_DOOR
|
||||||
|
: Sound.ITEM_SHIELD_BLOCK;
|
||||||
|
|
||||||
|
knockLocation.getWorld().playSound(knockLocation, sound, SoundCategory.PLAYERS, 1f, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull List<Listener> listeners() {
|
||||||
|
return List.of(new KnockDoorListener());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.knockDoor;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.data.type.Door;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.block.BlockDamageAbortEvent;
|
||||||
|
|
||||||
|
public class KnockDoorListener extends ApplianceListener<KnockDoor> {
|
||||||
|
@EventHandler
|
||||||
|
public void onKnock(BlockDamageAbortEvent event) {
|
||||||
|
if(event.getPlayer().getGameMode() != GameMode.SURVIVAL) return;
|
||||||
|
Block block = event.getBlock();
|
||||||
|
if(!(block.getBlockData() instanceof Door)) return;
|
||||||
|
getAppliance().knockAtDoor(event.getPlayer(), block);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.knockDoor;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.SelectSetting;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class KnockDoorSetting extends SelectSetting implements CategorizedSetting {
|
||||||
|
private static final String namespace = KnockDoorSetting.class.getSimpleName().toLowerCase(Locale.ROOT);
|
||||||
|
public static Options.Option disabled = new Options.Option("Deaktiviert", new NamespacedKey(namespace, "disabled"));
|
||||||
|
public static Options.Option knockSingleTime = new Options.Option("Einmal an der Tür anklopfen", new NamespacedKey(namespace, "single"));
|
||||||
|
public static Options.Option knockThreeTimes = new Options.Option("Dreimal an der Tür anklopfen", new NamespacedKey(namespace, "three"));
|
||||||
|
|
||||||
|
public KnockDoorSetting() {
|
||||||
|
super(
|
||||||
|
Settings.Key.KnockDoors,
|
||||||
|
new Options(List.of(disabled, knockSingleTime, knockThreeTimes))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SettingCategory category() {
|
||||||
|
return SettingCategory.Gameplay;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String title() {
|
||||||
|
return "Klopfen an Türen";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String description() {
|
||||||
|
return "Klopft durch das schlagen an eine Tür an.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Material icon() {
|
||||||
|
return Material.BELL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Options.Option defaultValue() {
|
||||||
|
return disabled;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.maintenance;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
|
||||||
|
import eu.mhsl.craftattack.spawn.config.Configuration;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Maintenance extends Appliance {
|
||||||
|
private boolean isInMaintenance;
|
||||||
|
private final String configKey = "enabled";
|
||||||
|
|
||||||
|
public Maintenance() {
|
||||||
|
super("maintenance");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
this.isInMaintenance = localConfig().getBoolean(configKey, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(boolean enabled) {
|
||||||
|
this.isInMaintenance = enabled;
|
||||||
|
localConfig().set(configKey, enabled);
|
||||||
|
Configuration.saveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInMaintenance() {
|
||||||
|
return isInMaintenance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull List<ApplianceCommand<?>> commands() {
|
||||||
|
return List.of(new MaintenanceCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull List<Listener> listeners() {
|
||||||
|
return List.of(new PreventMaintenanceJoinListener());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.maintenance;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class MaintenanceCommand extends ApplianceCommand<Maintenance> {
|
||||||
|
Map<String, Boolean> arguments = Map.of("enable", true, "disable", false);
|
||||||
|
|
||||||
|
public MaintenanceCommand() {
|
||||||
|
super("maintanance");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception {
|
||||||
|
if(args.length != 1 || !arguments.containsKey(args[0])) throw new Error("Argument 'enable' oder 'disable' gefordert!");
|
||||||
|
getAppliance().setState(arguments.get(args[0]));
|
||||||
|
sender.sendMessage(String.format("Maintanance: %b", getAppliance().isInMaintenance()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
|
return arguments.keySet().stream().toList();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.maintenance;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||||
|
import eu.mhsl.craftattack.spawn.util.text.DisconnectInfo;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.player.PlayerLoginEvent;
|
||||||
|
|
||||||
|
public class PreventMaintenanceJoinListener extends ApplianceListener<Maintenance> {
|
||||||
|
@EventHandler
|
||||||
|
public void onJoin(PlayerLoginEvent event) {
|
||||||
|
if(!getAppliance().isInMaintenance()) return;
|
||||||
|
if(event.getPlayer().hasPermission("bypassMaintainance")) return;
|
||||||
|
|
||||||
|
DisconnectInfo disconnectInfo = new DisconnectInfo(
|
||||||
|
"Wartunsarbeiten",
|
||||||
|
"Zurzeit können nur Admins dem Server beitreten!",
|
||||||
|
"Bitte warte bis die Warungsarbeiten wieder deaktiviert werden.",
|
||||||
|
event.getPlayer().getUniqueId()
|
||||||
|
);
|
||||||
|
|
||||||
|
event.disallow(PlayerLoginEvent.Result.KICK_OTHER, disconnectInfo.getComponent());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.optionLinks;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ServerLinks;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
|
public class OptionLinks extends Appliance {
|
||||||
|
record ComponentSupplier() {}
|
||||||
|
record UriSupplier(Player player) {}
|
||||||
|
record UriConsumer(String uri) {}
|
||||||
|
record SuppliedLink(Function<ComponentSupplier, Component> component, Function<UriSupplier, UriConsumer> uri) {}
|
||||||
|
|
||||||
|
List<SuppliedLink> links = List.of(
|
||||||
|
new SuppliedLink(
|
||||||
|
componentSupplier -> Component.text("CraftAttack Homepage", NamedTextColor.GOLD),
|
||||||
|
uriSupplier -> new UriConsumer("https://mhsl.eu/craftattack")
|
||||||
|
),
|
||||||
|
new SuppliedLink(
|
||||||
|
componentSupplier -> Component.text("Regeln", NamedTextColor.GOLD),
|
||||||
|
uriSupplier -> new UriConsumer("https://mhsl.eu/craftattack/rules")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
Bukkit.getServer().getServerLinks().getLinks()
|
||||||
|
.forEach(serverLink -> Bukkit.getServer().getServerLinks().removeLink(serverLink));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServerLinks(Player player) {
|
||||||
|
ServerLinks playerLinks = Bukkit.getServerLinks().copy();
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(Main.instance(), () -> {
|
||||||
|
this.links.forEach(suppliedLink -> {
|
||||||
|
Component component = suppliedLink.component.apply(new ComponentSupplier());
|
||||||
|
String uri = suppliedLink.uri.apply(new UriSupplier(player)).uri;
|
||||||
|
|
||||||
|
try {
|
||||||
|
playerLinks.addLink(component, URI.create(uri));
|
||||||
|
} catch(IllegalArgumentException e) {
|
||||||
|
Main.logger().log(Level.INFO, String.format("Failed to create OptionLink '%s' for player '%s'", uri, player.getName()), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
player.sendLinks(playerLinks);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull List<Listener> listeners() {
|
||||||
|
return List.of(new UpdateLinksListener());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.optionLinks;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
|
||||||
|
public class UpdateLinksListener extends ApplianceListener<OptionLinks> {
|
||||||
|
@EventHandler
|
||||||
|
public void onJoin(PlayerJoinEvent event) {
|
||||||
|
getAppliance().setServerLinks(event.getPlayer());
|
||||||
|
}
|
||||||
|
}
|
@ -38,7 +38,7 @@ public class Outlawed extends Appliance {
|
|||||||
if(!player.isOnline()) return;
|
if(!player.isOnline()) return;
|
||||||
if(status != Status.FORCED) return;
|
if(status != Status.FORCED) return;
|
||||||
try {
|
try {
|
||||||
Main.instance().getAppliance(Whitelist.class).integrityCheck(player);
|
queryAppliance(Whitelist.class).integrityCheck(player);
|
||||||
} catch(DisconnectInfo.Throwable e) {
|
} catch(DisconnectInfo.Throwable e) {
|
||||||
Bukkit.getScheduler().runTask(Main.instance(), () -> e.getDisconnectScreen().applyKick(player));
|
Bukkit.getScheduler().runTask(Main.instance(), () -> e.getDisconnectScreen().applyKick(player));
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ public class Outlawed extends Appliance {
|
|||||||
|
|
||||||
private void setLawStatus(Player player, Status status) {
|
private void setLawStatus(Player player, Status status) {
|
||||||
playerStatusMap.put(player, status);
|
playerStatusMap.put(player, status);
|
||||||
Main.instance().getAppliance(DisplayName.class).update(player);
|
queryAppliance(DisplayName.class).update(player);
|
||||||
|
|
||||||
List<String> newList = localConfig().getStringList(voluntarilyEntry);
|
List<String> newList = localConfig().getStringList(voluntarilyEntry);
|
||||||
if(status.equals(Status.VOLUNTARILY)) {
|
if(status.equals(Status.VOLUNTARILY)) {
|
||||||
@ -93,7 +93,7 @@ public class Outlawed extends Appliance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTimeout(Player player) {
|
private boolean isTimeout(Player player) {
|
||||||
return timeouts.get(player.getUniqueId()) < System.currentTimeMillis() - timeoutInMs;
|
return timeouts.getOrDefault(player.getUniqueId(), 0L) > System.currentTimeMillis() - timeoutInMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTimeout(Player player) {
|
private void setTimeout(Player player) {
|
||||||
@ -127,7 +127,7 @@ public class Outlawed extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<Listener> eventHandlers() {
|
protected List<Listener> listeners() {
|
||||||
return List.of(new OutlawedReminderListener());
|
return List.of(new OutlawedReminderListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.packSelect;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class ChangePackCommand extends ApplianceCommand.PlayerChecked<PackSelect> {
|
||||||
|
public static final String commandName = "texturepack";
|
||||||
|
public ChangePackCommand() {
|
||||||
|
super(commandName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception {
|
||||||
|
getAppliance().openPackInventory(getPlayer());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.packSelect;
|
||||||
|
|
||||||
|
import com.google.gson.*;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.CachedApplianceSupplier;
|
||||||
|
import eu.mhsl.craftattack.spawn.util.inventory.HeadBuilder;
|
||||||
|
import eu.mhsl.craftattack.spawn.util.text.ComponentUtil;
|
||||||
|
import net.kyori.adventure.resource.ResourcePackInfo;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class PackConfiguration extends CachedApplianceSupplier<PackSelect> {
|
||||||
|
public record Pack(UUID id, String name, String description, String author, ResourcePackInfo info, String icon) {
|
||||||
|
public ItemStack buildItem() {
|
||||||
|
ItemStack stack = HeadBuilder.getCustomTextureHead(icon);
|
||||||
|
ItemMeta meta = stack.getItemMeta();
|
||||||
|
meta.itemName(Component.text(id.toString()));
|
||||||
|
meta.displayName(Component.text(name(), NamedTextColor.GOLD));
|
||||||
|
List<Component> lore = new ArrayList<>();
|
||||||
|
lore.add(Component.text("Autor: ", NamedTextColor.DARK_GRAY).append(Component.text(author)));
|
||||||
|
lore.add(Component.text(" "));
|
||||||
|
lore.addAll(
|
||||||
|
ComponentUtil.lineBreak(description())
|
||||||
|
.map(s -> Component.text(s, NamedTextColor.GRAY))
|
||||||
|
.toList()
|
||||||
|
);
|
||||||
|
lore.add(Component.text(" "));
|
||||||
|
meta.lore(lore);
|
||||||
|
stack.setItemMeta(meta);
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equalsItem(ItemStack other) {
|
||||||
|
String itemName = PlainTextComponentSerializer.plainText().serialize(other.getItemMeta().itemName());
|
||||||
|
try {
|
||||||
|
return UUID.fromString(itemName).equals(id);
|
||||||
|
} catch(IllegalArgumentException ignored) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public record PackList(List<Pack> packs) {
|
||||||
|
public Optional<Pack> findFromItem(ItemStack itemStack) {
|
||||||
|
return packs.stream()
|
||||||
|
.filter(pack -> pack.equalsItem(itemStack))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public record SerializedPackList(List<UUID> packs) {}
|
||||||
|
|
||||||
|
private final PackList packList;
|
||||||
|
private final Gson gson = new GsonBuilder().create();
|
||||||
|
|
||||||
|
private PackConfiguration() {
|
||||||
|
this.packList = new PackList(new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private PackConfiguration(String data) {
|
||||||
|
SerializedPackList serializedData = gson.fromJson(data, SerializedPackList.class);
|
||||||
|
|
||||||
|
var availablePackMap = getAppliance().availablePacks.packs().stream()
|
||||||
|
.collect(Collectors.toMap(PackConfiguration.Pack::id, pack -> pack));
|
||||||
|
|
||||||
|
this.packList = new PackList(
|
||||||
|
serializedData.packs().stream()
|
||||||
|
.map(availablePackMap::get)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
);
|
||||||
|
|
||||||
|
if (this.packList.packs().isEmpty()) throw new IllegalArgumentException("Serialized data does not contain any valid data!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PackConfiguration deserialize(String data) {
|
||||||
|
return new PackConfiguration(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PackConfiguration empty() {
|
||||||
|
return new PackConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String serialize() {
|
||||||
|
return gson.toJson(new SerializedPackList(this.packList.packs().stream().map(Pack::id).toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Pack> getPackList() {
|
||||||
|
return packList.packs();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,171 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.packSelect;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.CachedApplianceSupplier;
|
||||||
|
import eu.mhsl.craftattack.spawn.util.IteratorUtil;
|
||||||
|
import eu.mhsl.craftattack.spawn.util.inventory.ItemBuilder;
|
||||||
|
import eu.mhsl.craftattack.spawn.util.inventory.PlaceholderItems;
|
||||||
|
import eu.mhsl.craftattack.spawn.util.world.InteractSounds;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.inventory.ClickType;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
public class PackConfigurationInventory extends CachedApplianceSupplier<PackSelect> {
|
||||||
|
private final PackConfiguration packConfiguration;
|
||||||
|
private final Player inventoryOwner;
|
||||||
|
private final Inventory inventory;
|
||||||
|
|
||||||
|
private final ItemStack reset = ItemBuilder.of(Material.BARRIER)
|
||||||
|
.displayName(Component.text("Zurücksetzen", NamedTextColor.RED))
|
||||||
|
.lore("Alle gewählten Texturepacks werden entfernt")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private final ItemStack info = ItemBuilder.of(Material.OAK_HANGING_SIGN)
|
||||||
|
.displayName(Component.text("Texturepacks", NamedTextColor.GOLD))
|
||||||
|
.lore(
|
||||||
|
"Wähle aus der oberen Liste eine oder mehrere Texturepacks aus. " +
|
||||||
|
"Ändere die anzuwendende Reihenfolge durch Links/Rechtsklick in der unteren Liste. " +
|
||||||
|
"Klicke auf Speichern um die Änderungen anzuwenden!"
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private final ItemStack save = ItemBuilder.of(Material.GREEN_WOOL)
|
||||||
|
.displayName(Component.text("Anwenden", NamedTextColor.GREEN))
|
||||||
|
.lore("Die Ausgewählten Texturepacks werden in der entsprechenden Reihenfolge angewandt. Das Anwenden kann durch den Download je nach Internetgeschwindigkeit eine Weile dauern.")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private final ItemStack unusedSlot = ItemBuilder.of(Material.LIME_STAINED_GLASS_PANE)
|
||||||
|
.displayName(Component.text("Freier Slot", NamedTextColor.GREEN))
|
||||||
|
.lore("Klicke auf ein Texturepack um es hinzuzufügen.")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
public PackConfigurationInventory(PackConfiguration packConfiguration, Player inventoryOwner) {
|
||||||
|
this.packConfiguration = packConfiguration;
|
||||||
|
this.inventoryOwner = inventoryOwner;
|
||||||
|
this.inventory = Bukkit.createInventory(null, 9 * 6, Component.text("Texturepacks"));
|
||||||
|
this.draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Inventory getInventory() {
|
||||||
|
return inventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleClick(@Nullable ItemStack clickedItem, int slot, ClickType clickType) {
|
||||||
|
if(clickedItem == null) return;
|
||||||
|
if(clickedItem.equals(reset)) reset();
|
||||||
|
if(clickedItem.equals(save)) apply();
|
||||||
|
|
||||||
|
if(slot >= 9 && slot < 9 * 4) {
|
||||||
|
getAppliance().availablePacks.findFromItem(clickedItem)
|
||||||
|
.ifPresent(this::toggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(slot >= 9 * 5) {
|
||||||
|
getAppliance().availablePacks.findFromItem(clickedItem)
|
||||||
|
.ifPresent(pack -> {
|
||||||
|
switch(clickType) {
|
||||||
|
case RIGHT -> move(pack, true);
|
||||||
|
case LEFT -> move(pack, false);
|
||||||
|
case MIDDLE -> toggle(pack);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void move(PackConfiguration.Pack pack, boolean moveToRight) {
|
||||||
|
List<PackConfiguration.Pack> packs = packConfiguration.getPackList();
|
||||||
|
int index = packs.indexOf(pack);
|
||||||
|
|
||||||
|
if (index != -1) {
|
||||||
|
int newIndex = moveToRight ? index + 1 : index - 1;
|
||||||
|
if (newIndex >= 0 && newIndex < packs.size()) Collections.swap(packs, index, newIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
InteractSounds.of(inventoryOwner).click();
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toggle(PackConfiguration.Pack pack) {
|
||||||
|
if(packConfiguration.getPackList().contains(pack)) {
|
||||||
|
packConfiguration.getPackList().remove(pack);
|
||||||
|
} else {
|
||||||
|
packConfiguration.getPackList().add(pack);
|
||||||
|
}
|
||||||
|
|
||||||
|
InteractSounds.of(inventoryOwner).click();
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reset() {
|
||||||
|
packConfiguration.getPackList().clear();
|
||||||
|
InteractSounds.of(inventoryOwner).delete();
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void apply() {
|
||||||
|
inventoryOwner.closeInventory();
|
||||||
|
InteractSounds.of(inventoryOwner).success();
|
||||||
|
Bukkit.getScheduler().runTask(Main.instance(), () -> getAppliance().setPack(inventoryOwner, packConfiguration));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void draw() {
|
||||||
|
inventory.clear();
|
||||||
|
|
||||||
|
inventory.setItem(0, packConfiguration.getPackList().isEmpty() ? PlaceholderItems.grayStainedGlassPane : reset);
|
||||||
|
IteratorUtil.times(3, () -> inventory.addItem(PlaceholderItems.grayStainedGlassPane));
|
||||||
|
inventory.setItem(4, info);
|
||||||
|
IteratorUtil.times(3, () -> inventory.addItem(PlaceholderItems.grayStainedGlassPane));
|
||||||
|
inventory.setItem(8, save);
|
||||||
|
|
||||||
|
IteratorUtil.iterateListInGlobal(
|
||||||
|
9,
|
||||||
|
getAppliance().availablePacks.packs().stream()
|
||||||
|
.filter(pack -> !packConfiguration.getPackList().contains(pack))
|
||||||
|
.limit(9 * 3)
|
||||||
|
.map(pack -> {
|
||||||
|
ItemBuilder stack = ItemBuilder.of(pack.buildItem());
|
||||||
|
if(packConfiguration.getPackList().contains(pack)) stack.glint();
|
||||||
|
return stack.build();
|
||||||
|
})
|
||||||
|
.toList(),
|
||||||
|
inventory::setItem
|
||||||
|
);
|
||||||
|
|
||||||
|
IntStream.range(9 * 4, 9 * 5)
|
||||||
|
.forEach(slot -> inventory.setItem(slot, PlaceholderItems.grayStainedGlassPane));
|
||||||
|
|
||||||
|
IteratorUtil.iterateListInGlobal(
|
||||||
|
9 * 5,
|
||||||
|
IteratorUtil.expandList(
|
||||||
|
IntStream.range(0, Math.min(packConfiguration.getPackList().size(), 9))
|
||||||
|
.mapToObj(i -> {
|
||||||
|
PackConfiguration.Pack pack = packConfiguration.getPackList().get(i);
|
||||||
|
ItemBuilder builder = ItemBuilder.of(pack.buildItem());
|
||||||
|
|
||||||
|
builder
|
||||||
|
.displayName(existing -> Component.text(String.format("#%s ", i + 1), NamedTextColor.LIGHT_PURPLE).append(existing))
|
||||||
|
.appendLore(Component.text("➡ Rechtsklick um nach Rechts zu verschieben", NamedTextColor.AQUA))
|
||||||
|
.appendLore(Component.text("⬅ Linksklick um nach Links zu verschieben", NamedTextColor.AQUA))
|
||||||
|
.appendLore(Component.text("\uD83D\uDDD1 Mausradklick um zu entfernen", NamedTextColor.AQUA));
|
||||||
|
return builder.build();
|
||||||
|
})
|
||||||
|
.toList(),
|
||||||
|
9,
|
||||||
|
unusedSlot
|
||||||
|
),
|
||||||
|
inventory::setItem
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,139 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.packSelect;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.packSelect.listeners.ClosePackInventoryListener;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.packSelect.listeners.ClickPackInventoryListener;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.packSelect.listeners.SetPacksOnJoinListener;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||||
|
import net.kyori.adventure.resource.ResourcePackInfo;
|
||||||
|
import net.kyori.adventure.resource.ResourcePackRequest;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.persistence.PersistentDataContainer;
|
||||||
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class PackSelect extends Appliance {
|
||||||
|
private static final NamespacedKey packKey = new NamespacedKey(Main.instance(), PackSelect.class.getName().toLowerCase(Locale.ROOT));
|
||||||
|
|
||||||
|
public final PackConfiguration.PackList availablePacks = new PackConfiguration.PackList(new ArrayList<>());
|
||||||
|
public final Map<Player, PackConfigurationInventory> openInventories = new WeakHashMap<>();
|
||||||
|
|
||||||
|
public PackSelect() {
|
||||||
|
super("packselect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
Settings.instance().declareSetting(PackSelectSetting.class);
|
||||||
|
|
||||||
|
List<Map<?, ?>> packs = localConfig().getMapList("packs");
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(
|
||||||
|
Main.instance(),
|
||||||
|
() -> packs.stream()
|
||||||
|
.flatMap(pack -> pack.entrySet().stream())
|
||||||
|
.forEach(pack -> {
|
||||||
|
@SuppressWarnings("unchecked") Map<String, String> packData = (Map<String, String>) pack.getValue();
|
||||||
|
|
||||||
|
try {
|
||||||
|
ResourcePackInfo resourcePackInfo = ResourcePackInfoFactory
|
||||||
|
.createResourcePackInfo(URI.create(packData.get("url")), packData.get("hash"))
|
||||||
|
.join();
|
||||||
|
|
||||||
|
PackConfiguration.Pack packToAdd = new PackConfiguration.Pack(
|
||||||
|
UUID.nameUUIDFromBytes(pack.getKey().toString().getBytes()),
|
||||||
|
packData.get("name"),
|
||||||
|
packData.get("description"),
|
||||||
|
packData.get("author"),
|
||||||
|
resourcePackInfo,
|
||||||
|
packData.get("icon")
|
||||||
|
);
|
||||||
|
availablePacks.packs().add(packToAdd);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Main.logger().warning(String.format("Failed to add pack %s: %s", packData.get("name"), e.getMessage()));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PackConfiguration getPackConfigurationForPlayer(Player player) {
|
||||||
|
PersistentDataContainer persistentDataContainer = player.getPersistentDataContainer();
|
||||||
|
try {
|
||||||
|
String serialized = persistentDataContainer.get(packKey, PersistentDataType.STRING);
|
||||||
|
Objects.requireNonNull(serialized);
|
||||||
|
return PackConfiguration.deserialize(serialized);
|
||||||
|
} catch(IllegalArgumentException | NullPointerException exception) {
|
||||||
|
return PackConfiguration.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openPackInventory(Player player) {
|
||||||
|
PackConfigurationInventory packInventory = new PackConfigurationInventory(getPackConfigurationForPlayer(player), player);
|
||||||
|
player.openInventory(packInventory.getInventory());
|
||||||
|
openInventories.put(player, packInventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPack(Player player, PackConfiguration packConfiguration) {
|
||||||
|
player.getPersistentDataContainer().set(packKey, PersistentDataType.STRING, packConfiguration.serialize());
|
||||||
|
|
||||||
|
int packCount = packConfiguration.getPackList().size();
|
||||||
|
if(packCount > 0) {
|
||||||
|
player.sendMessage(
|
||||||
|
Component.text(
|
||||||
|
String.format("%s heruntergeladen und hinzugefügt...", packCount > 1 ? "Texturenpakete werden" : "Texturenpaket wird"),
|
||||||
|
NamedTextColor.DARK_GREEN
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
player.sendResourcePacks(
|
||||||
|
ResourcePackRequest.resourcePackRequest()
|
||||||
|
.packs(
|
||||||
|
packConfiguration.getPackList().stream()
|
||||||
|
.map(PackConfiguration.Pack::info)
|
||||||
|
.toList()
|
||||||
|
.reversed()
|
||||||
|
)
|
||||||
|
.replace(true)
|
||||||
|
.required(true)
|
||||||
|
.prompt(
|
||||||
|
Component.text()
|
||||||
|
.append(Component.text("Bestätige um fortzufahren! Du kannst deine Entscheidung jederzeit mit ", NamedTextColor.GRAY))
|
||||||
|
.append(Component.text(String.format("/%s ", ChangePackCommand.commandName), NamedTextColor.GOLD))
|
||||||
|
.append(Component.text("ändern.", NamedTextColor.GRAY))
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNotPackInventory(Player player, Inventory inventory) {
|
||||||
|
PackConfigurationInventory packConfigurationInventory = this.openInventories.get(player);
|
||||||
|
if(packConfigurationInventory == null) return true;
|
||||||
|
return packConfigurationInventory.getInventory() != inventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull List<ApplianceCommand<?>> commands() {
|
||||||
|
return List.of(new ChangePackCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull List<Listener> listeners() {
|
||||||
|
return List.of(
|
||||||
|
new ClosePackInventoryListener(),
|
||||||
|
new ClickPackInventoryListener(),
|
||||||
|
new SetPacksOnJoinListener()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.packSelect;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.ActionSetting;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.inventory.ClickType;
|
||||||
|
|
||||||
|
public class PackSelectSetting extends ActionSetting implements CategorizedSetting {
|
||||||
|
@Override
|
||||||
|
protected String title() {
|
||||||
|
return "Texturepacks";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String description() {
|
||||||
|
return "Stelle dein persönliches Texturepack aus einer kuratierten Auswahl zusammen und gestalte deine Spielerfahrung individuell.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Material icon() {
|
||||||
|
return Material.PAINTING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onAction(Player player, ClickType clickType) {
|
||||||
|
Main.instance().getAppliance(PackSelect.class).openPackInventory(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SettingCategory category() {
|
||||||
|
return SettingCategory.Visuals;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.packSelect;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
|
import net.kyori.adventure.resource.ResourcePackInfo;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public class ResourcePackInfoFactory {
|
||||||
|
|
||||||
|
private static boolean isValidHash(@Nullable String hash) {
|
||||||
|
return hash != null && hash.length() == 40;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @NotNull CompletableFuture<ResourcePackInfo> createResourcePackInfo(@NotNull URI resourcePackUrl, @Nullable String hash) {
|
||||||
|
if (isValidHash(hash)) {
|
||||||
|
return CompletableFuture.completedFuture(
|
||||||
|
ResourcePackInfo.resourcePackInfo(UUID.nameUUIDFromBytes(hash.getBytes()), resourcePackUrl, hash)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
|
try {
|
||||||
|
Main.logger().info(String.format("Start calculating SHA1 Hash of %s", resourcePackUrl));
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) resourcePackUrl.toURL().openConnection();
|
||||||
|
connection.setRequestMethod("GET");
|
||||||
|
connection.connect();
|
||||||
|
|
||||||
|
try (InputStream inputStream = connection.getInputStream()) {
|
||||||
|
MessageDigest sha1Digest = MessageDigest.getInstance("SHA-1");
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||||
|
sha1Digest.update(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
String sha1Hex = bytesToHex(sha1Digest.digest());
|
||||||
|
|
||||||
|
Main.logger().info(String.format("Calculating SHA1 Hash of %s completed: %s", resourcePackUrl, sha1Hex));
|
||||||
|
return ResourcePackInfo.resourcePackInfo(UUID.nameUUIDFromBytes(sha1Hex.getBytes()), resourcePackUrl, sha1Hex);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
String error = String.format("Error whilst SHA1 calculation of %s: %s", resourcePackUrl, e.getMessage());
|
||||||
|
Main.logger().warning(error);
|
||||||
|
throw new RuntimeException(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String bytesToHex(byte[] bytes) {
|
||||||
|
StringBuilder hexString = new StringBuilder(bytes.length * 2);
|
||||||
|
for (byte b : bytes) {
|
||||||
|
hexString.append(String.format("%02x", b));
|
||||||
|
}
|
||||||
|
return hexString.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.packSelect.listeners;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.packSelect.PackSelect;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
|
||||||
|
public class ClickPackInventoryListener extends ApplianceListener<PackSelect> {
|
||||||
|
@EventHandler
|
||||||
|
public void interact(InventoryClickEvent event) {
|
||||||
|
if(!(event.getWhoClicked() instanceof Player player)) return;
|
||||||
|
if(getAppliance().isNotPackInventory(player, event.getInventory())) return;
|
||||||
|
event.setCancelled(true);
|
||||||
|
|
||||||
|
getAppliance().openInventories.get(player).handleClick(
|
||||||
|
event.getCurrentItem(),
|
||||||
|
event.getSlot(),
|
||||||
|
event.getClick()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.packSelect.listeners;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.packSelect.PackSelect;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||||
|
|
||||||
|
public class ClosePackInventoryListener extends ApplianceListener<PackSelect> {
|
||||||
|
@EventHandler
|
||||||
|
public void onClose(InventoryCloseEvent event) {
|
||||||
|
if(!(event.getPlayer() instanceof Player player)) return;
|
||||||
|
if(getAppliance().isNotPackInventory(player, event.getInventory())) return;
|
||||||
|
getAppliance().openInventories.remove(player);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.packSelect.listeners;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.packSelect.PackSelect;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
|
||||||
|
public class SetPacksOnJoinListener extends ApplianceListener<PackSelect> {
|
||||||
|
@EventHandler
|
||||||
|
public void onJoin(PlayerJoinEvent event) {
|
||||||
|
Bukkit.getScheduler().runTask(
|
||||||
|
Main.instance(),
|
||||||
|
() -> getAppliance().setPack(event.getPlayer(), getAppliance().getPackConfigurationForPlayer(event.getPlayer()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -50,7 +50,7 @@ public class PanicBan extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<Listener> eventHandlers() {
|
protected List<Listener> listeners() {
|
||||||
return List.of(new PanicBanJoinListener());
|
return List.of(new PanicBanJoinListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ public class PlayerLimit extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<Listener> eventHandlers() {
|
protected List<Listener> listeners() {
|
||||||
return List.of(
|
return List.of(
|
||||||
new PlayerLimiterListener()
|
new PlayerLimiterListener()
|
||||||
);
|
);
|
||||||
|
@ -3,11 +3,13 @@ package eu.mhsl.craftattack.spawn.appliances.portableCrafting;
|
|||||||
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
|
||||||
public class OnCraftingTableUseListener extends ApplianceListener<PortableCrafting> {
|
public class OnCraftingTableUseListener extends ApplianceListener<PortableCrafting> {
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void inInteract(PlayerInteractEvent event) {
|
public void inInteract(PlayerInteractEvent event) {
|
||||||
|
if(!event.getAction().equals(Action.RIGHT_CLICK_AIR)) return;
|
||||||
if(!event.getMaterial().equals(Material.CRAFTING_TABLE)) return;
|
if(!event.getMaterial().equals(Material.CRAFTING_TABLE)) return;
|
||||||
getAppliance().openFor(event.getPlayer());
|
getAppliance().openFor(event.getPlayer());
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,18 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class PortableCrafting extends Appliance {
|
public class PortableCrafting extends Appliance {
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
Settings.instance().declareSetting(PortableCraftingSetting.class);
|
||||||
|
}
|
||||||
|
|
||||||
public void openFor(Player player) {
|
public void openFor(Player player) {
|
||||||
if(!Settings.instance().getSetting(player, Settings.Key.EnablePortableCrafting, Boolean.class)) return;
|
if(!Settings.instance().getSetting(player, Settings.Key.EnablePortableCrafting, Boolean.class)) return;
|
||||||
player.openWorkbench(null, true);
|
player.openWorkbench(null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected @NotNull List<Listener> eventHandlers() {
|
protected @NotNull List<Listener> listeners() {
|
||||||
return List.of(new OnCraftingTableUseListener());
|
return List.of(new OnCraftingTableUseListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package eu.mhsl.craftattack.spawn.appliances.settings.settings;
|
package eu.mhsl.craftattack.spawn.appliances.portableCrafting;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
@ -175,7 +175,7 @@ public class ProjectStart extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<Listener> eventHandlers() {
|
protected List<Listener> listeners() {
|
||||||
return List.of(
|
return List.of(
|
||||||
new PlayerInvincibleListener(),
|
new PlayerInvincibleListener(),
|
||||||
new NoAdvancementsListener()
|
new NoAdvancementsListener()
|
||||||
|
@ -2,6 +2,6 @@ package eu.mhsl.craftattack.spawn.appliances.settings;
|
|||||||
|
|
||||||
public enum SettingCategory {
|
public enum SettingCategory {
|
||||||
Gameplay,
|
Gameplay,
|
||||||
Chat,
|
Visuals,
|
||||||
Misc,
|
Misc,
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
package eu.mhsl.craftattack.spawn.appliances.settings;
|
package eu.mhsl.craftattack.spawn.appliances.settings;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.Main;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.Setting;
|
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.Setting;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.listeners.OpenSettingsShortcutListener;
|
import eu.mhsl.craftattack.spawn.appliances.settings.listeners.OpenSettingsShortcutListener;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.listeners.SettingsInventoryListener;
|
import eu.mhsl.craftattack.spawn.appliances.settings.listeners.SettingsInventoryListener;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.settings.*;
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -14,13 +12,14 @@ import org.bukkit.event.Listener;
|
|||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
import java.util.WeakHashMap;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class Settings extends Appliance {
|
public class Settings extends Appliance {
|
||||||
private static Settings settingsInstance;
|
private static Settings settingsInstance;
|
||||||
|
private final Set<Class<? extends Setting<?>>> declaredSettings = new HashSet<>();
|
||||||
|
|
||||||
public enum Key {
|
public enum Key {
|
||||||
TechnicalTab,
|
TechnicalTab,
|
||||||
@ -31,13 +30,24 @@ public class Settings extends Appliance {
|
|||||||
SignEdit,
|
SignEdit,
|
||||||
HotbarReplacer,
|
HotbarReplacer,
|
||||||
ChatMentions,
|
ChatMentions,
|
||||||
|
DoubleDoors,
|
||||||
|
KnockDoors,
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Settings instance() {
|
public static Settings instance() {
|
||||||
if(settingsInstance != null) return settingsInstance;
|
if(settingsInstance != null) return settingsInstance;
|
||||||
Settings instance = Main.instance().getAppliance(Settings.class);
|
Settings.settingsInstance = queryAppliance(Settings.class);
|
||||||
Settings.settingsInstance = instance;
|
return settingsInstance;
|
||||||
return instance;
|
}
|
||||||
|
|
||||||
|
public void declareSetting(Class<? extends Setting<?>> setting) {
|
||||||
|
this.declaredSettings.add(setting);
|
||||||
|
this.settingsCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
Settings.instance().declareSetting(SettingsShortcutSetting.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public record OpenSettingsInventory(Inventory inventory, List<Setting<?>> settings) {
|
public record OpenSettingsInventory(Inventory inventory, List<Setting<?>> settings) {
|
||||||
@ -49,25 +59,31 @@ public class Settings extends Appliance {
|
|||||||
private List<Setting<?>> getSettings(Player player) {
|
private List<Setting<?>> getSettings(Player player) {
|
||||||
if(settingsCache.containsKey(player)) return settingsCache.get(player);
|
if(settingsCache.containsKey(player)) return settingsCache.get(player);
|
||||||
|
|
||||||
List<Setting<?>> settings = List.of(
|
List<Setting<?>> settings = this.declaredSettings.stream()
|
||||||
new PortableCraftingSetting(),
|
.map(clazz -> {
|
||||||
new AutoShulkerSetting(),
|
try {
|
||||||
new SignEditSetting(),
|
return clazz.getDeclaredConstructor();
|
||||||
new HotbarReplaceSetting(),
|
} catch (NoSuchMethodException e) {
|
||||||
new ChatMentionSetting(),
|
throw new RuntimeException(String.format("Setting '%s' does not have an accessible constructor", clazz.getName()), e);
|
||||||
new ShowJoinAndLeaveMessagesSetting(),
|
}
|
||||||
new TechnicalTablistSetting(),
|
})
|
||||||
new SettingsShortcutSetting()
|
.map(constructor -> {
|
||||||
);
|
try {
|
||||||
|
return constructor.newInstance();
|
||||||
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||||
|
throw new RuntimeException(String.format("Failed to create instance of setting '%s'", constructor.getDeclaringClass().getName()), e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.peek(setting -> setting.initializeFromPlayer(player))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
settings.forEach(setting -> setting.initializeFromPlayer(player));
|
|
||||||
this.settingsCache.put(player, settings);
|
this.settingsCache.put(player, settings);
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T getSetting(Player player, Key key, Class<T> clazz) {
|
public <T> T getSetting(Player player, Key key, Class<T> clazz) {
|
||||||
Setting<?> setting = getSettings(player).stream()
|
Setting<?> setting = getSettings(player).stream()
|
||||||
.filter(s -> s.getKey().equals(key))
|
.filter(s -> Objects.equals(s.getKey(), key))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElseThrow();
|
.orElseThrow();
|
||||||
|
|
||||||
@ -119,11 +135,15 @@ public class Settings extends Appliance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int calculateInvSize(List<Setting<?>> settings) {
|
private int calculateInvSize(List<Setting<?>> settings) {
|
||||||
int countOfUncategorized = (int) settings.stream().filter(setting -> !(setting instanceof CategorizedSetting)).count();
|
int countOfUncategorized = (int) settings.stream()
|
||||||
|
.filter(setting -> !(setting instanceof CategorizedSetting))
|
||||||
|
.count();
|
||||||
|
|
||||||
return Arrays.stream(SettingCategory.values())
|
return Arrays.stream(SettingCategory.values())
|
||||||
.map(settingCategory -> settings.stream()
|
.map(settingCategory -> settings.stream()
|
||||||
.filter(setting -> setting instanceof CategorizedSetting)
|
.filter(setting -> setting instanceof CategorizedSetting)
|
||||||
.filter(setting -> ((CategorizedSetting) setting).category().equals(settingCategory))
|
.map(setting -> (CategorizedSetting) setting)
|
||||||
|
.filter(categorizedSetting -> categorizedSetting.category().equals(settingCategory))
|
||||||
.count())
|
.count())
|
||||||
.map(itemCount -> itemCount + countOfUncategorized)
|
.map(itemCount -> itemCount + countOfUncategorized)
|
||||||
.map(itemCount -> (int) Math.ceil((double) itemCount / 9))
|
.map(itemCount -> (int) Math.ceil((double) itemCount / 9))
|
||||||
@ -148,7 +168,7 @@ public class Settings extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<Listener> eventHandlers() {
|
protected List<Listener> listeners() {
|
||||||
return List.of(
|
return List.of(
|
||||||
new SettingsInventoryListener(),
|
new SettingsInventoryListener(),
|
||||||
new OpenSettingsShortcutListener()
|
new OpenSettingsShortcutListener()
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
package eu.mhsl.craftattack.spawn.appliances.settings.settings;
|
package eu.mhsl.craftattack.spawn.appliances.settings;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.BoolSetting;
|
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.BoolSetting;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
|
@ -0,0 +1,50 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.settings.datatypes;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.inventory.ClickType;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.bukkit.persistence.PersistentDataContainer;
|
||||||
|
|
||||||
|
|
||||||
|
public abstract class ActionSetting extends Setting<Void> {
|
||||||
|
public ActionSetting() {
|
||||||
|
super(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void onAction(Player player, ClickType clickType);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemMeta buildMeta(ItemMeta meta) {
|
||||||
|
meta.displayName(Component.text(title(), NamedTextColor.WHITE));
|
||||||
|
meta.lore(buildDescription(description()));
|
||||||
|
return meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void change(Player player, ClickType clickType) {
|
||||||
|
onAction(player, clickType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void defaultValue() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void fromStorage(PersistentDataContainer container) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void toStorage(PersistentDataContainer container, Void value) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> dataType() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void state() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ package eu.mhsl.craftattack.spawn.appliances.settings.datatypes;
|
|||||||
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.inventory.ClickType;
|
import org.bukkit.event.inventory.ClickType;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
import org.bukkit.persistence.PersistentDataContainer;
|
import org.bukkit.persistence.PersistentDataContainer;
|
||||||
@ -47,7 +48,7 @@ public abstract class BoolSetting extends Setting<Boolean> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void change(ClickType clickType) {
|
protected void change(Player player, ClickType clickType) {
|
||||||
this.state = !this.state;
|
this.state = !this.state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import com.google.gson.Gson;
|
|||||||
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.inventory.ClickType;
|
import org.bukkit.event.inventory.ClickType;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
import org.bukkit.persistence.PersistentDataContainer;
|
import org.bukkit.persistence.PersistentDataContainer;
|
||||||
@ -87,7 +88,7 @@ public abstract class MultiBoolSetting<T> extends Setting<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void change(ClickType clickType) {
|
protected void change(Player player, ClickType clickType) {
|
||||||
var recordComponents = this.state.getClass().getRecordComponents();
|
var recordComponents = this.state.getClass().getRecordComponents();
|
||||||
|
|
||||||
int currentIndex = IntStream.range(0, recordComponents.length)
|
int currentIndex = IntStream.range(0, recordComponents.length)
|
||||||
|
@ -5,6 +5,7 @@ import net.kyori.adventure.text.Component;
|
|||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.inventory.ClickType;
|
import org.bukkit.event.inventory.ClickType;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
import org.bukkit.persistence.PersistentDataContainer;
|
import org.bukkit.persistence.PersistentDataContainer;
|
||||||
@ -57,7 +58,7 @@ public abstract class SelectSetting extends Setting<SelectSetting.Options.Option
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void change(ClickType clickType) {
|
protected void change(Player player, ClickType clickType) {
|
||||||
int optionModifier = clickType.equals(ClickType.LEFT) ? 1 : -1;
|
int optionModifier = clickType.equals(ClickType.LEFT) ? 1 : -1;
|
||||||
List<Options.Option> options = this.options.options;
|
List<Options.Option> options = this.options.options;
|
||||||
this.state = IntStream.range(0, options.size())
|
this.state = IntStream.range(0, options.size())
|
||||||
|
@ -37,7 +37,7 @@ public abstract class Setting<TDataType> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void triggerChange(Player p, ClickType clickType) {
|
public void triggerChange(Player p, ClickType clickType) {
|
||||||
this.change(clickType);
|
this.change(p, clickType);
|
||||||
toStorage(p.getPersistentDataContainer(), this.state());
|
toStorage(p.getPersistentDataContainer(), this.state());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ public abstract class Setting<TDataType> {
|
|||||||
protected abstract String description();
|
protected abstract String description();
|
||||||
protected abstract Material icon();
|
protected abstract Material icon();
|
||||||
public abstract ItemMeta buildMeta(ItemMeta meta);
|
public abstract ItemMeta buildMeta(ItemMeta meta);
|
||||||
protected abstract void change(ClickType clickType);
|
protected abstract void change(Player player, ClickType clickType);
|
||||||
protected abstract TDataType defaultValue();
|
protected abstract TDataType defaultValue();
|
||||||
protected abstract void fromStorage(PersistentDataContainer container);
|
protected abstract void fromStorage(PersistentDataContainer container);
|
||||||
protected abstract void toStorage(PersistentDataContainer container, TDataType value);
|
protected abstract void toStorage(PersistentDataContainer container, TDataType value);
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.snowballKnockback;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SnowballKnockback extends Appliance {
|
||||||
|
public void dealSnowballKnockback(LivingEntity entity, Entity snowball) {
|
||||||
|
entity.damage(0.1);
|
||||||
|
entity.knockback(0.4, -snowball.getVelocity().getX(), -snowball.getVelocity().getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
protected List<Listener> listeners() {
|
||||||
|
return List.of(new SnowballKnockbackListener());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.snowballKnockback;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||||
|
import org.bukkit.entity.*;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.entity.ProjectileHitEvent;
|
||||||
|
|
||||||
|
public class SnowballKnockbackListener extends ApplianceListener<SnowballKnockback> {
|
||||||
|
@EventHandler
|
||||||
|
public void onSnowballHit(ProjectileHitEvent event) {
|
||||||
|
if(event.getHitEntity() == null) return;
|
||||||
|
if(!event.getEntityType().equals(EntityType.SNOWBALL)) return;
|
||||||
|
if(!(event.getHitEntity() instanceof LivingEntity hitEntity)) return;
|
||||||
|
|
||||||
|
Entity snowball = event.getEntity();
|
||||||
|
getAppliance().dealSnowballKnockback(hitEntity, snowball);
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,8 @@ import org.bukkit.entity.Player;
|
|||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.management.OperatingSystemMXBean;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -23,6 +25,7 @@ import java.util.List;
|
|||||||
public class Tablist extends Appliance {
|
public class Tablist extends Appliance {
|
||||||
private final RainbowComponent serverName = new RainbowComponent(" CraftAttack 7 ", 7, 3);
|
private final RainbowComponent serverName = new RainbowComponent(" CraftAttack 7 ", 7, 3);
|
||||||
private NetworkMonitor networkMonitor;
|
private NetworkMonitor networkMonitor;
|
||||||
|
private OperatingSystemMXBean systemMonitor;
|
||||||
|
|
||||||
public Tablist() {
|
public Tablist() {
|
||||||
super("tablist");
|
super("tablist");
|
||||||
@ -30,8 +33,12 @@ public class Tablist extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
|
Settings.instance().declareSetting(TechnicalTablistSetting.class);
|
||||||
|
|
||||||
int tabRefreshRate = 3;
|
int tabRefreshRate = 3;
|
||||||
this.networkMonitor = new NetworkMonitor(localConfig().getString("interface"), Duration.ofSeconds(1));
|
this.networkMonitor = new NetworkMonitor(localConfig().getString("interface"), Duration.ofSeconds(1));
|
||||||
|
this.systemMonitor = ManagementFactory.getOperatingSystemMXBean();
|
||||||
|
|
||||||
Bukkit.getScheduler().runTaskTimerAsynchronously(
|
Bukkit.getScheduler().runTaskTimerAsynchronously(
|
||||||
Main.instance(),
|
Main.instance(),
|
||||||
() -> IteratorUtil.onlinePlayers(this::updateHeader),
|
() -> IteratorUtil.onlinePlayers(this::updateHeader),
|
||||||
@ -63,8 +70,9 @@ public class Tablist extends Appliance {
|
|||||||
.append(ComponentUtil.getFormattedPing(player)).appendNewline()
|
.append(ComponentUtil.getFormattedPing(player)).appendNewline()
|
||||||
.append(ComponentUtil.getFormattedNetworkStats(
|
.append(ComponentUtil.getFormattedNetworkStats(
|
||||||
this.networkMonitor.getTraffic(),
|
this.networkMonitor.getTraffic(),
|
||||||
this.networkMonitor.getPackets())
|
this.networkMonitor.getPackets()
|
||||||
).appendNewline();
|
)).appendNewline()
|
||||||
|
.append(ComponentUtil.getFormattedSystemStats(this.systemMonitor)).appendNewline();
|
||||||
}
|
}
|
||||||
|
|
||||||
player.sendPlayerListHeader(header);
|
player.sendPlayerListHeader(header);
|
||||||
@ -76,7 +84,7 @@ public class Tablist extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<Listener> eventHandlers() {
|
protected List<Listener> listeners() {
|
||||||
return List.of(new TablistListener());
|
return List.of(new TablistListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package eu.mhsl.craftattack.spawn.appliances.settings.settings;
|
package eu.mhsl.craftattack.spawn.appliances.tablist;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
import eu.mhsl.craftattack.spawn.appliances.settings.CategorizedSetting;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
import eu.mhsl.craftattack.spawn.appliances.settings.SettingCategory;
|
@ -14,7 +14,7 @@ public class TitleClear extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<Listener> eventHandlers() {
|
protected List<Listener> listeners() {
|
||||||
return List.of(
|
return List.of(
|
||||||
new TitleClearListener()
|
new TitleClearListener()
|
||||||
);
|
);
|
||||||
|
@ -64,7 +64,7 @@ public class Whitelist extends Appliance {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Main.instance().getAppliance(Outlawed.class).updateForcedStatus(player, timestampRelevant(user.outlawed_until));
|
queryAppliance(Outlawed.class).updateForcedStatus(player, timestampRelevant(user.outlawed_until));
|
||||||
|
|
||||||
String purePlayerName = Floodgate.isBedrock(player)
|
String purePlayerName = Floodgate.isBedrock(player)
|
||||||
? Floodgate.getBedrockPlayer(player).getUsername()
|
? Floodgate.getBedrockPlayer(player).getUsername()
|
||||||
@ -144,7 +144,7 @@ public class Whitelist extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<Listener> eventHandlers() {
|
protected List<Listener> listeners() {
|
||||||
return List.of(
|
return List.of(
|
||||||
new PlayerJoinListener()
|
new PlayerJoinListener()
|
||||||
);
|
);
|
||||||
|
@ -44,15 +44,13 @@ public class WorldMuseum extends Appliance {
|
|||||||
|
|
||||||
public void handleVillagerInteraction(Player player) {
|
public void handleVillagerInteraction(Player player) {
|
||||||
if(Floodgate.isBedrock(player)) {
|
if(Floodgate.isBedrock(player)) {
|
||||||
Floodgate.runBedrockOnly(player, floodgatePlayer -> {
|
Floodgate.runBedrockOnly(player, floodgatePlayer -> floodgatePlayer.sendForm(
|
||||||
floodgatePlayer.sendForm(
|
SimpleForm.builder()
|
||||||
SimpleForm.builder()
|
.title("Nicht unterstützt")
|
||||||
.title("Nicht unterstützt")
|
.content("Bedrock-Spieler werden derzeit für das Weltenmuseum aus Kompatiblitätsgründen nicht zugelassen! Tut uns Leid.")
|
||||||
.content("Bedrock-Spieler werden derzeit für das Weltenmuseum aus Kompatiblitätsgründen nicht zugelassen! Tut uns Leid.")
|
.button("Ok")
|
||||||
.button("Ok")
|
.build()
|
||||||
.build()
|
));
|
||||||
);
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +66,7 @@ public class WorldMuseum extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected List<Listener> eventHandlers() {
|
protected List<Listener> listeners() {
|
||||||
return List.of(
|
return List.of(
|
||||||
new PlayerInteractAtEntityEventListener(this.villager.getUniqueId(), playerInteractAtEntityEvent -> handleVillagerInteraction(playerInteractAtEntityEvent.getPlayer())),
|
new PlayerInteractAtEntityEventListener(this.villager.getUniqueId(), playerInteractAtEntityEvent -> handleVillagerInteraction(playerInteractAtEntityEvent.getPlayer())),
|
||||||
new DismissInventoryOpenFromHolder(this.villager.getUniqueId())
|
new DismissInventoryOpenFromHolder(this.villager.getUniqueId())
|
||||||
|
@ -0,0 +1,99 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.yearRank;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.TextComponent;
|
||||||
|
import net.kyori.adventure.text.event.ClickEvent;
|
||||||
|
import net.kyori.adventure.text.event.HoverEvent;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class YearRank extends Appliance {
|
||||||
|
record CraftAttackYear(String name) {}
|
||||||
|
private final Map<UUID, List<CraftAttackYear>> rankMap = new HashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
File folder = new File(Main.instance().getDataFolder(), "yearRank");
|
||||||
|
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
folder.mkdirs();
|
||||||
|
|
||||||
|
Optional<File[]> dataFolders = Optional.ofNullable(folder.listFiles());
|
||||||
|
if(dataFolders.isEmpty()) return;
|
||||||
|
|
||||||
|
List.of(dataFolders.get()).forEach(playerDataFolder -> {
|
||||||
|
Optional<File[]> datFiles = Optional.ofNullable(playerDataFolder.listFiles());
|
||||||
|
if(datFiles.isEmpty()) return;
|
||||||
|
|
||||||
|
CraftAttackYear craftAttackYear = new CraftAttackYear(playerDataFolder.getName());
|
||||||
|
|
||||||
|
Arrays.stream(datFiles.get())
|
||||||
|
.map(file -> file.getName().split("\\.")[0])
|
||||||
|
.distinct()
|
||||||
|
.map(UUID::fromString)
|
||||||
|
.peek(uuid -> rankMap.computeIfAbsent(uuid, p -> new ArrayList<>()))
|
||||||
|
.forEach(uuid -> rankMap.get(uuid).add(craftAttackYear));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable Component getNamePrefix(Player player) {
|
||||||
|
if(!rankMap.containsKey(player.getUniqueId())) return null;
|
||||||
|
int yearCount = rankMap.get(player.getUniqueId()).size();
|
||||||
|
if(yearCount <= 3) return null;
|
||||||
|
|
||||||
|
return Component.text()
|
||||||
|
.append(Component.text("[\uD83C\uDF1F]", NamedTextColor.GOLD))
|
||||||
|
.hoverEvent(HoverEvent.showText(
|
||||||
|
Component.text(String.format("Langzeitspieler: %s ist bereits seit %d Jahren dabei!", player.getName(), yearCount))
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component listYearRanks() {
|
||||||
|
TextComponent.Builder builder = Component.text();
|
||||||
|
builder.append(Component.text("Top 30 Spieler: ", NamedTextColor.GOLD));
|
||||||
|
rankMap.keySet().stream()
|
||||||
|
.map(uuid -> Map.entry(uuid, rankMap.get(uuid).size()))
|
||||||
|
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
|
||||||
|
.limit(30)
|
||||||
|
.forEach(entry -> builder
|
||||||
|
.appendNewline()
|
||||||
|
.append(Component.text(entry.getKey().toString(), NamedTextColor.GRAY)
|
||||||
|
.hoverEvent(HoverEvent.showText(Component.text(entry.getKey().toString())))
|
||||||
|
.clickEvent(ClickEvent.copyToClipboard(entry.getKey().toString())))
|
||||||
|
.append(Component.text(": "))
|
||||||
|
.append(Component.text(entry.getValue(), NamedTextColor.GOLD)));
|
||||||
|
|
||||||
|
builder
|
||||||
|
.appendNewline()
|
||||||
|
.appendNewline()
|
||||||
|
.append(Component.text("Übersischt:", NamedTextColor.GOLD));
|
||||||
|
|
||||||
|
rankMap.values().stream()
|
||||||
|
.mapMulti(Iterable::forEach)
|
||||||
|
.filter(o -> o instanceof CraftAttackYear)
|
||||||
|
.map(o -> (CraftAttackYear) o)
|
||||||
|
.distinct()
|
||||||
|
.forEach(craftAttackYear -> builder
|
||||||
|
.appendNewline()
|
||||||
|
.append(Component.text(craftAttackYear.name, NamedTextColor.GRAY))
|
||||||
|
.append(Component.text(": "))
|
||||||
|
.append(Component.text(rankMap.keySet().stream()
|
||||||
|
.filter(uuid -> rankMap.get(uuid).contains(craftAttackYear)).count())));
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull List<ApplianceCommand<?>> commands() {
|
||||||
|
return List.of(new YearRankCommand());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.yearRank;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class YearRankCommand extends ApplianceCommand<YearRank> {
|
||||||
|
public YearRankCommand() {
|
||||||
|
super("yearRank");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception {
|
||||||
|
sender.sendMessage(getAppliance().listYearRanks());
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package eu.mhsl.craftattack.spawn.config;
|
package eu.mhsl.craftattack.spawn.config;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.Main;
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
@ -10,9 +11,11 @@ public class Configuration {
|
|||||||
private static final String configName = "config.yml";
|
private static final String configName = "config.yml";
|
||||||
private static final File configFile = new File(Main.instance().getDataFolder().getAbsolutePath() + "/" + configName);
|
private static final File configFile = new File(Main.instance().getDataFolder().getAbsolutePath() + "/" + configName);
|
||||||
public static FileConfiguration cfg;
|
public static FileConfiguration cfg;
|
||||||
|
public static ConfigurationSection pluginConfig;
|
||||||
|
|
||||||
public static void readConfig() {
|
public static void readConfig() {
|
||||||
cfg = YamlConfiguration.loadConfiguration(configFile);
|
cfg = YamlConfiguration.loadConfiguration(configFile);
|
||||||
|
pluginConfig = cfg.getConfigurationSection("plugin");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void saveChanges() {
|
public static void saveChanges() {
|
||||||
|
@ -5,9 +5,14 @@ import org.bukkit.GameRule;
|
|||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class IteratorUtil {
|
public class IteratorUtil {
|
||||||
public static void worlds(Consumer<World> world) {
|
public static void worlds(Consumer<World> world) {
|
||||||
@ -25,4 +30,25 @@ public class IteratorUtil {
|
|||||||
public static void setGameRules(Map<GameRule<Boolean>, Boolean> rules, boolean inverse) {
|
public static void setGameRules(Map<GameRule<Boolean>, Boolean> rules, boolean inverse) {
|
||||||
rules.forEach((gameRule, value) -> IteratorUtil.worlds(world -> world.setGameRule(gameRule, value ^ inverse)));
|
rules.forEach((gameRule, value) -> IteratorUtil.worlds(world -> world.setGameRule(gameRule, value ^ inverse)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void times(int times, Runnable callback) {
|
||||||
|
IntStream.range(0, times).forEach(value -> callback.run());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> void iterateListInGlobal(int sectionStart, List<T> list, BiConsumer<Integer, T> callback) {
|
||||||
|
IntStream.range(sectionStart, sectionStart + list.size())
|
||||||
|
.forEach(value -> callback.accept(value, list.get(value - sectionStart)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void iterateLocalInGlobal(int sectionStart, int localLength, BiConsumer<Integer, Integer> callback) {
|
||||||
|
IntStream.range(sectionStart, sectionStart + localLength)
|
||||||
|
.forEach(value -> callback.accept(value, value + sectionStart));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> expandList(List<T> list, int targetSize, T defaultValue) {
|
||||||
|
return Stream.concat(
|
||||||
|
list.stream(),
|
||||||
|
Stream.generate(() -> defaultValue).limit(Math.max(0, targetSize - list.size()))
|
||||||
|
).collect(Collectors.toList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.util.inventory;
|
||||||
|
|
||||||
|
import com.destroystokyo.paper.profile.PlayerProfile;
|
||||||
|
import com.destroystokyo.paper.profile.ProfileProperty;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.SkullMeta;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class HeadBuilder {
|
||||||
|
public static ItemStack getCustomTextureHead(String base64) {
|
||||||
|
ItemStack head = new ItemStack(Material.PLAYER_HEAD);
|
||||||
|
SkullMeta meta = (SkullMeta) head.getItemMeta();
|
||||||
|
PlayerProfile profile = Bukkit.createProfile(UUID.nameUUIDFromBytes(base64.getBytes()), null);
|
||||||
|
profile.setProperty(new ProfileProperty("textures", base64));
|
||||||
|
meta.setPlayerProfile(profile);
|
||||||
|
head.setItemMeta(meta);
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,92 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.util.inventory;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.util.text.ComponentUtil;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class ItemBuilder {
|
||||||
|
private final ItemStack itemStack;
|
||||||
|
|
||||||
|
@Contract(value = "_ -> new", pure = true)
|
||||||
|
public static @NotNull ItemBuilder of(Material material) {
|
||||||
|
return new ItemBuilder(material);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Contract(value = "_ -> new", pure = true)
|
||||||
|
public static @NotNull ItemBuilder of(ItemStack itemStack) {
|
||||||
|
return new ItemBuilder(itemStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemBuilder(Material material) {
|
||||||
|
this.itemStack = ItemStack.of(material);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemBuilder(ItemStack itemStack) {
|
||||||
|
this.itemStack = itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder displayName(Component displayName) {
|
||||||
|
return this.withMeta(itemMeta -> itemMeta.displayName(displayName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder displayName(Function<Component, Component> process) {
|
||||||
|
return this.displayName(process.apply(itemStack.displayName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder lore(String text) {
|
||||||
|
return this.lore(text, 50, NamedTextColor.GRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder lore(String text, NamedTextColor color) {
|
||||||
|
return this.lore(text, 50, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder lore(String text, int linebreak, NamedTextColor color) {
|
||||||
|
return this.withMeta(itemMeta -> itemMeta.lore(
|
||||||
|
ComponentUtil.lineBreak(text, linebreak)
|
||||||
|
.map(s -> Component.text(s, color))
|
||||||
|
.toList()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder appendLore(Component text) {
|
||||||
|
List<Component> lore = itemStack.lore();
|
||||||
|
Objects.requireNonNull(lore, "Cannot append lore to Item without lore");
|
||||||
|
lore.add(text);
|
||||||
|
return this.withMeta(itemMeta -> itemMeta.lore(lore));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder noStacking() {
|
||||||
|
return this.withMeta(itemMeta -> itemMeta.setMaxStackSize(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder glint() {
|
||||||
|
return this.withMeta(itemMeta -> itemMeta.setEnchantmentGlintOverride(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder amount(int amount) {
|
||||||
|
this.itemStack.setAmount(amount);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder withMeta(Consumer<ItemMeta> callback) {
|
||||||
|
ItemMeta meta = this.itemStack.getItemMeta();
|
||||||
|
callback.accept(meta);
|
||||||
|
this.itemStack.setItemMeta(meta);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack build() {
|
||||||
|
return this.itemStack;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.util.inventory;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
public class PlaceholderItems {
|
||||||
|
private static final Component emptyName = Component.text(" ");
|
||||||
|
public static final ItemStack grayStainedGlassPane = ItemBuilder.of(Material.GRAY_STAINED_GLASS_PANE)
|
||||||
|
.displayName(emptyName)
|
||||||
|
.noStacking()
|
||||||
|
.build();
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package eu.mhsl.craftattack.spawn.util.server;
|
package eu.mhsl.craftattack.spawn.util.server;
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.geysermc.cumulus.form.SimpleForm;
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
|
|
||||||
@ -24,4 +25,22 @@ public class Floodgate {
|
|||||||
public static void runJavaOnly(Player p, Consumer<Player> callback) {
|
public static void runJavaOnly(Player p, Consumer<Player> callback) {
|
||||||
if(!isBedrock(p)) callback.accept(p);
|
if(!isBedrock(p)) callback.accept(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void throwWithMessageWhenBedrock(Player player) {
|
||||||
|
if(isBedrock(player)) {
|
||||||
|
SimpleForm.builder()
|
||||||
|
.title("Nicht unterstützt")
|
||||||
|
.content("Bedrock-Spieler werden derzeit für diese Aktion unterstützt! Tut uns Leid.")
|
||||||
|
.button("Ok")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
throw new BedrockNotSupportedException(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BedrockNotSupportedException extends RuntimeException {
|
||||||
|
public BedrockNotSupportedException(Player player) {
|
||||||
|
super(String.format("Bedrock player '%s' tried using an Operation which is unsupported.", player.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import org.bukkit.Bukkit;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.lang.management.OperatingSystemMXBean;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -21,6 +22,13 @@ public class ComponentUtil {
|
|||||||
return Component.text().append(a.appendNewline().append(b)).build();
|
return Component.text().append(a.appendNewline().append(b)).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TextComponent appendWithSpace(Component a, Component b) {
|
||||||
|
return Component.text().append(a).append(Component.text(" ")).append(b).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stream<String> lineBreak(String text) {
|
||||||
|
return lineBreak(text, 50);
|
||||||
|
}
|
||||||
public static Stream<String> lineBreak(String text, int charactersPerLine) {
|
public static Stream<String> lineBreak(String text, int charactersPerLine) {
|
||||||
List<String> lines = new ArrayList<>();
|
List<String> lines = new ArrayList<>();
|
||||||
String[] words = text.split(" ");
|
String[] words = text.split(" ");
|
||||||
@ -46,34 +54,6 @@ public class ComponentUtil {
|
|||||||
return lines.collect(Collectors.joining("\n"));
|
return lines.collect(Collectors.joining("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Component getFormattedTPS() {
|
|
||||||
double[] tpsValues = Bukkit.getTPS();
|
|
||||||
|
|
||||||
double min1 = Math.min(1.0, Math.max(0.0, tpsValues[0] / 20.0));
|
|
||||||
double min2 = Math.min(1.0, Math.max(0.0, tpsValues[1] / 20.0));
|
|
||||||
double min3 = Math.min(1.0, Math.max(0.0, tpsValues[2] / 20.0));
|
|
||||||
|
|
||||||
int red1 = (int) (255 * (1.0 - min1));
|
|
||||||
int green1 = (int) (255 * min1);
|
|
||||||
int red2 = (int) (255 * (1.0 - min2));
|
|
||||||
int green2 = (int) (255 * min2);
|
|
||||||
int red3 = (int) (255 * (1.0 - min3));
|
|
||||||
int green3 = (int) (255 * min3);
|
|
||||||
|
|
||||||
TextColor tpsColor1 = TextColor.color(red1, green1, 0);
|
|
||||||
TextColor tpsColor2 = TextColor.color(red2, green2, 0);
|
|
||||||
TextColor tpsColor3 = TextColor.color(red3, green3, 0);
|
|
||||||
|
|
||||||
return Component.text()
|
|
||||||
.append(Component.text("TPS 1, 5, 15m: ", NamedTextColor.GRAY))
|
|
||||||
.append(Component.text(String.format("%.2f", tpsValues[0]), tpsColor1))
|
|
||||||
.append(Component.text(", "))
|
|
||||||
.append(Component.text(String.format("%.2f", tpsValues[1]), tpsColor2))
|
|
||||||
.append(Component.text(", "))
|
|
||||||
.append(Component.text(String.format("%.2f", tpsValues[2]), tpsColor3))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Component getFormattedTickTimes(boolean detailed) {
|
public static Component getFormattedTickTimes(boolean detailed) {
|
||||||
long[] times = Bukkit.getServer().getTickTimes();
|
long[] times = Bukkit.getServer().getTickTimes();
|
||||||
float mspt = ((float) Arrays.stream(times).sum() / times.length) * 1.0E-6f;
|
float mspt = ((float) Arrays.stream(times).sum() / times.length) * 1.0E-6f;
|
||||||
@ -132,14 +112,72 @@ public class ComponentUtil {
|
|||||||
public static Component getFormattedNetworkStats(NetworkMonitor.Traffic traffic, NetworkMonitor.Packets packets) {
|
public static Component getFormattedNetworkStats(NetworkMonitor.Traffic traffic, NetworkMonitor.Packets packets) {
|
||||||
return Component.text()
|
return Component.text()
|
||||||
.append(Component.text(
|
.append(Component.text(
|
||||||
DataSizeConverter.convertBytesToHumanReadable(traffic.rxBytes()) + " ↓ " + NumberAbbreviation.abbreviateNumber(packets.rxCount()) + "pps",
|
DataSizeConverter.convertBytesPerSecond(traffic.rxBytes()) + " ↓ " + NumberAbbreviation.abbreviateNumber(packets.rxCount()) + "pps",
|
||||||
NamedTextColor.GREEN
|
NamedTextColor.GREEN
|
||||||
))
|
))
|
||||||
.append(Component.text(" | ", NamedTextColor.GRAY))
|
.append(Component.text(" | ", NamedTextColor.GRAY))
|
||||||
.append(Component.text(
|
.append(Component.text(
|
||||||
DataSizeConverter.convertBytesToHumanReadable(traffic.txBytes()) + " ↑ " + NumberAbbreviation.abbreviateNumber(packets.rxCount()) + "pps",
|
DataSizeConverter.convertBytesPerSecond(traffic.txBytes()) + " ↑ " + NumberAbbreviation.abbreviateNumber(packets.rxCount()) + "pps",
|
||||||
NamedTextColor.RED
|
NamedTextColor.RED
|
||||||
))
|
))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Component getFormattedSystemStats(OperatingSystemMXBean systemMonitor) {
|
||||||
|
if(!(systemMonitor instanceof com.sun.management.OperatingSystemMXBean monitor))
|
||||||
|
return Component.text("Could not get System information", NamedTextColor.DARK_GRAY);
|
||||||
|
|
||||||
|
return Component.text()
|
||||||
|
.append(Component.text("proc: ", NamedTextColor.GRAY))
|
||||||
|
.append(Component.text(
|
||||||
|
String.format("%.0f%%cpu", monitor.getProcessCpuLoad() * 100),
|
||||||
|
NamedTextColor.GOLD
|
||||||
|
))
|
||||||
|
.append(Component.text(" | ", NamedTextColor.GRAY))
|
||||||
|
.append(Component.text(
|
||||||
|
String.format("%s time", DataSizeConverter.formatCpuTimeToHumanReadable(monitor.getProcessCpuTime())),
|
||||||
|
NamedTextColor.LIGHT_PURPLE
|
||||||
|
))
|
||||||
|
.append(Component.text(" | ", NamedTextColor.GRAY))
|
||||||
|
.append(Component.text(
|
||||||
|
String.format(
|
||||||
|
"%s free, %s committed RAM",
|
||||||
|
DataSizeConverter.formatBytesToHumanReadable(monitor.getFreeMemorySize()),
|
||||||
|
DataSizeConverter.formatBytesToHumanReadable(monitor.getCommittedVirtualMemorySize())
|
||||||
|
),
|
||||||
|
NamedTextColor.DARK_AQUA
|
||||||
|
))
|
||||||
|
.appendNewline()
|
||||||
|
.append(Component.text("sys: ", NamedTextColor.GRAY))
|
||||||
|
.append(Component.text(
|
||||||
|
String.format("%.0f%%cpu", monitor.getCpuLoad() * 100),
|
||||||
|
NamedTextColor.GOLD
|
||||||
|
))
|
||||||
|
.append(Component.text(" | ", NamedTextColor.GRAY))
|
||||||
|
.append(Component.text(
|
||||||
|
String.format(
|
||||||
|
"1min %.2f load avg (%.0f%%)",
|
||||||
|
monitor.getSystemLoadAverage(),
|
||||||
|
(monitor.getSystemLoadAverage() / monitor.getAvailableProcessors()) * 100
|
||||||
|
),
|
||||||
|
NamedTextColor.LIGHT_PURPLE
|
||||||
|
))
|
||||||
|
.append(Component.text(" | ", NamedTextColor.GRAY))
|
||||||
|
.append(Component.text(
|
||||||
|
String.format("%s total RAM", DataSizeConverter.formatBytesToHumanReadable(monitor.getTotalMemorySize())),
|
||||||
|
NamedTextColor.DARK_AQUA
|
||||||
|
))
|
||||||
|
.appendNewline()
|
||||||
|
.append(Component.text(
|
||||||
|
String.format(
|
||||||
|
"%s(%s) \uD83D\uDE80 on %s with %s cpu(s)",
|
||||||
|
monitor.getName(),
|
||||||
|
monitor.getVersion(),
|
||||||
|
monitor.getArch(),
|
||||||
|
monitor.getAvailableProcessors()
|
||||||
|
),
|
||||||
|
NamedTextColor.GRAY
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package eu.mhsl.craftattack.spawn.util.text;
|
package eu.mhsl.craftattack.spawn.util.text;
|
||||||
|
|
||||||
public class DataSizeConverter {
|
public class DataSizeConverter {
|
||||||
public static String convertBytesToHumanReadable(long bytes) {
|
public static String convertBytesPerSecond(long bytes) {
|
||||||
double kbits = bytes * 8.0 / 1000.0;
|
double kbits = bytes * 8.0 / 1000.0;
|
||||||
double mbits = kbits / 1000.0;
|
double mbits = kbits / 1000.0;
|
||||||
|
|
||||||
@ -11,4 +11,31 @@ public class DataSizeConverter {
|
|||||||
return String.format("%.2f Kbit", kbits);
|
return String.format("%.2f Kbit", kbits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String formatBytesToHumanReadable(long bytes) {
|
||||||
|
String[] units = {"B", "KB", "MB", "GB", "TB", "PB", "EB"};
|
||||||
|
int unitIndex = 0;
|
||||||
|
double readableSize = bytes;
|
||||||
|
|
||||||
|
while (readableSize >= 1024 && unitIndex < units.length - 1) {
|
||||||
|
readableSize /= 1024;
|
||||||
|
unitIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.format("%.2f%s", readableSize, units[unitIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatCpuTimeToHumanReadable(long nanoseconds) {
|
||||||
|
if (nanoseconds < 0) return "unsupported";
|
||||||
|
|
||||||
|
long seconds = nanoseconds / 1_000_000_000;
|
||||||
|
long minutes = seconds / 60;
|
||||||
|
long hours = minutes / 60;
|
||||||
|
long days = hours / 24;
|
||||||
|
|
||||||
|
seconds %= 60;
|
||||||
|
minutes %= 60;
|
||||||
|
hours %= 60;
|
||||||
|
return String.format("%dd%dh%dm%ds", days, hours, minutes, seconds);
|
||||||
|
}
|
||||||
}
|
}
|
@ -6,12 +6,12 @@ import net.kyori.adventure.text.format.TextColor;
|
|||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
|
||||||
public class RainbowComponent {
|
public class RainbowComponent {
|
||||||
private int hueOffset = 0;
|
private float hueOffset = 0;
|
||||||
private final String text;
|
private final String text;
|
||||||
private final int density;
|
private final int density;
|
||||||
private final int speed;
|
private final float speed;
|
||||||
|
|
||||||
public RainbowComponent(String text, int density, int speed) {
|
public RainbowComponent(String text, int density, float speed) {
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.density = density;
|
this.density = density;
|
||||||
this.speed = speed;
|
this.speed = speed;
|
||||||
@ -19,15 +19,16 @@ public class RainbowComponent {
|
|||||||
|
|
||||||
public Component getRainbowState() {
|
public Component getRainbowState() {
|
||||||
Component builder = Component.empty();
|
Component builder = Component.empty();
|
||||||
int hue = this.hueOffset;
|
float hue = this.hueOffset;
|
||||||
for(char c : text.toCharArray()) {
|
for (char c : text.toCharArray()) {
|
||||||
TextColor color = TextColor.color(Color.getHSBColor((float) hue / 360, 1, 1).getRGB());
|
float normalizedHue = (hue % 360) / 360;
|
||||||
|
TextColor color = TextColor.color(Color.getHSBColor(normalizedHue, 1, 1).getRGB());
|
||||||
builder = builder.append(Component.text(c).color(color));
|
builder = builder.append(Component.text(c).color(color));
|
||||||
hue += density;
|
hue += density;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.hueOffset > Byte.MAX_VALUE - speed) this.hueOffset = 0;
|
this.hueOffset = (this.hueOffset + speed) % 360;
|
||||||
this.hueOffset += (byte) speed;
|
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.util.world;
|
||||||
|
|
||||||
|
import net.kyori.adventure.key.Key;
|
||||||
|
import net.kyori.adventure.sound.Sound;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class InteractSounds {
|
||||||
|
private final Player player;
|
||||||
|
|
||||||
|
public static InteractSounds of(Player player) {
|
||||||
|
return new InteractSounds(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
private InteractSounds(Player player) {
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void playSound(org.bukkit.Sound sound) {
|
||||||
|
player.playSound(getSound(sound.key()), Sound.Emitter.self());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Sound getSound(Key soundKey) {
|
||||||
|
return Sound.sound(soundKey, Sound.Source.PLAYER, 1f, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void click() {
|
||||||
|
playSound(org.bukkit.Sound.UI_BUTTON_CLICK);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void success() {
|
||||||
|
playSound(org.bukkit.Sound.ENTITY_PLAYER_LEVELUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete() {
|
||||||
|
playSound(org.bukkit.Sound.ENTITY_SILVERFISH_DEATH);
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,7 @@
|
|||||||
|
plugin:
|
||||||
|
disabledAppliances:
|
||||||
|
- NameOfApplianceClass
|
||||||
|
|
||||||
worldMuseum:
|
worldMuseum:
|
||||||
uuid:
|
uuid:
|
||||||
connect-server-name: worldmuseum
|
connect-server-name: worldmuseum
|
||||||
@ -42,7 +46,7 @@ help:
|
|||||||
spawn: "Der Weltspawn befindet sich bei x:0 y:0 z:0"
|
spawn: "Der Weltspawn befindet sich bei x:0 y:0 z:0"
|
||||||
|
|
||||||
playerLimit:
|
playerLimit:
|
||||||
maxPlayers: 100
|
maxPlayers: 10
|
||||||
|
|
||||||
whitelist:
|
whitelist:
|
||||||
overrideIntegrityCheck: false
|
overrideIntegrityCheck: false
|
||||||
@ -50,3 +54,16 @@ whitelist:
|
|||||||
|
|
||||||
tablist:
|
tablist:
|
||||||
interface: eth0
|
interface: eth0
|
||||||
|
|
||||||
|
outlawed:
|
||||||
|
voluntarily: []
|
||||||
|
|
||||||
|
packselect:
|
||||||
|
packs:
|
||||||
|
- somepack:
|
||||||
|
name: "Texture pack name"
|
||||||
|
description: "Texture pack description"
|
||||||
|
author: "Pack Author(s)"
|
||||||
|
url: "https://example.com/download/pack.zip"
|
||||||
|
hash: "" # SHA1 hash of ZIP file (will be auto determined by the server on startup when not set)
|
||||||
|
icon: "" # base64 player-head texture, can be obtained from sites like https://minecraft-heads.com/ under developers > Value
|
@ -37,5 +37,8 @@ commands:
|
|||||||
panicBan:
|
panicBan:
|
||||||
vogelfrei:
|
vogelfrei:
|
||||||
settings:
|
settings:
|
||||||
|
texturepack:
|
||||||
|
maintanance:
|
||||||
|
yearRank:
|
||||||
msg:
|
msg:
|
||||||
r:
|
r:
|
Loading…
x
Reference in New Issue
Block a user