Base rewrite with appliance System

This commit is contained in:
Elias Müller 2023-10-24 20:49:44 +02:00
parent a8d37b82db
commit bb54482b5e
42 changed files with 1073 additions and 398 deletions

View File

@ -1,35 +1,69 @@
package eu.mhsl.craftattack.spawn; package eu.mhsl.craftattack.spawn;
import eu.mhsl.craftattack.spawn.chatMessages.ChatMessagesMain; import eu.mhsl.craftattack.spawn.appliance.Appliance;
import eu.mhsl.craftattack.spawn.util.ConfigUtil; import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarker;
import eu.mhsl.craftattack.spawn.worldmuseum.WorldMueseumMain; import eu.mhsl.craftattack.spawn.appliances.chatMessages.ChatMessages;
import eu.mhsl.craftattack.spawn.appliances.countdown.Countdown;
import eu.mhsl.craftattack.spawn.appliances.tablist.Tablist;
import eu.mhsl.craftattack.spawn.appliances.titleClear.TitleClear;
import eu.mhsl.craftattack.spawn.config.Configuration;
import eu.mhsl.craftattack.spawn.appliances.worldmuseum.WorldMuseum;
import org.bukkit.Bukkit;
import org.bukkit.event.HandlerList;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import java.lang.reflect.ParameterizedType;
import java.util.List;
public final class Main extends JavaPlugin { public final class Main extends JavaPlugin {
private static Main instance; private static Main instance;
private List<Appliance> appliances;
@Override @Override
public void onEnable() { public void onEnable() {
// init
instance = this; instance = this;
saveDefaultConfig(); saveDefaultConfig();
Configuration.readConfig();
// load parts appliances = List.of(
if ((boolean) ConfigUtil.getConfigUtil().getConfig().get("enableWorldMuseum")) WorldMueseumMain.onEnable(); new AdminMarker(),
if ((boolean) ConfigUtil.getConfigUtil().getConfig().get("enableChatMessageOverrides")) ChatMessagesMain.onEnable(); new WorldMuseum(),
// if ((boolean) ConfigUtil.getConfigUtil().getConfig().get("enableProjectstart")) ProjectstartMain.onEnable(); new TitleClear(),
new Countdown(),
new Tablist(),
new ChatMessages()
);
Bukkit.getLogger().info("Loading appliances...");
appliances.forEach(appliance -> {
appliance.initialize(this);
appliance.onEnable();
});
Bukkit.getLogger().info("Loaded " + appliances.size() + " appliances!");
getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
} }
@Override @Override
public void onDisable() { public void onDisable() {
if ((boolean) ConfigUtil.getConfigUtil().getConfig().get("enableWorldMuseum")) WorldMueseumMain.onDisable(); appliances.forEach(appliance -> {
if ((boolean) ConfigUtil.getConfigUtil().getConfig().get("enableChatMessageOverrides")) ChatMessagesMain.onDisable(); appliance.onDisable();
// if ((boolean) ConfigUtil.getConfigUtil().getConfig().get("enableProjectstart")) ProjectstartMain.onDisable(); appliance.destruct(this);
});
HandlerList.unregisterAll(this);
Bukkit.getScheduler().cancelTasks(this);
} }
public static Main getInstance() { public <T extends Appliance> T getAppliance(Class<T> clazz) {
return this.appliances.stream().filter(clazz::isInstance).map(clazz::cast).findFirst().orElseThrow();
}
@SuppressWarnings("unchecked")
public static <T> Class<T> getApplianceType(Class<?> clazz) {
return (Class<T>) ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[0];
}
public static Main instance() {
return instance; return instance;
} }
} }

View File

@ -0,0 +1,82 @@
package eu.mhsl.craftattack.spawn.appliance;
import eu.mhsl.craftattack.spawn.config.Configuration;
import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* Any implementation of this class can be seen as a "sub-plugin" with its own event handlers and commands.
* Appliances can be enabled or disabled independent of other appliances
*/
public abstract class Appliance {
private String localConfigPath;
public Appliance() {
}
/**
* Use this constructor to specify a config sub-path for use with the localConfig() method.
* @param localConfigPath sub path, if not found, the whole config will be used
*/
public Appliance(String localConfigPath) {
this.localConfigPath = localConfigPath;
}
/**
* Provides a list of listeners for the appliance. All listeners will be automatically registered.
* @return List of listeners
*/
@NotNull
protected List<Listener> eventHandlers() {
return new ArrayList<>();
}
/**
* Provides a list of commands for the appliance. All commands will be automatically registered.
* @return List of commands
*/
@NotNull
protected List<ApplianceCommand<?>> commands() {
return new ArrayList<>();
}
/**
* Provides a localized config section. Path can be set in appliance constructor.
* @return Section of configuration for your appliance
*/
@NotNull
public ConfigurationSection localConfig() {
return Optional.ofNullable(Configuration.cfg.getConfigurationSection(localConfigPath)).orElse(Configuration.cfg);
}
public void onEnable() {}
public void onDisable() {}
public void initialize(@NotNull JavaPlugin plugin) {
eventHandlers().forEach(listener -> Bukkit.getPluginManager().registerEvents(listener, plugin));
commands().forEach(command -> setCommandExecutor(plugin, command.commandName, command));
}
public void destruct(@NotNull JavaPlugin plugin) {
eventHandlers().forEach(HandlerList::unregisterAll);
commands().forEach(command -> setCommandExecutor(plugin, command.commandName, null));
}
private void setCommandExecutor(JavaPlugin plugin, String name, ApplianceCommand<?> executor) {
PluginCommand command = plugin.getCommand(name);
if(command != null) {
command.setExecutor(executor);
} else {
Bukkit.getLogger().warning("Command " + name + " is not specified in plugin.yml!");
}
}
}

View File

@ -0,0 +1,84 @@
package eu.mhsl.craftattack.spawn.appliance;
import eu.mhsl.craftattack.spawn.Main;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
/**
* Utility class which enables command name definition over a constructor.
*/
public abstract class ApplianceCommand<T extends Appliance> implements ApplianceSupplier<T>, CommandExecutor {
public String commandName;
private final T appliance;
protected Component errorMessage = Component.text("Error whilst executing command").color(NamedTextColor.RED);
public ApplianceCommand(String command) {
this.appliance = Main.instance().getAppliance(Main.getApplianceType(getClass()));
this.commandName = command;
}
public ApplianceCommand(String command, Component errorMessage) {
this(command);
this.errorMessage = errorMessage;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
try {
execute(sender, command, label, args);
} catch (Exception e) {
sender.sendMessage(errorMessage);
return false;
}
return true;
}
protected abstract void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args);
@Override
public T getAppliance() {
return appliance;
}
/**
* Utility class for command which can only be used as a Player. You can access the executing player with the getPlayer() method.
*/
public static abstract class PlayerChecked<T extends Appliance> extends ApplianceCommand<T> {
private Player player;
private Component notPlayerMessage = Component.text("This command can only be executed as an Player!").color(NamedTextColor.RED);
protected PlayerChecked(String command) {
super(command);
}
public PlayerChecked(String command, Component errorMessage) {
super(command, errorMessage);
}
protected PlayerChecked(String command, @Nullable Component errorMessage, Component notPlayerMessage) {
super(command);
this.errorMessage = Optional.ofNullable(errorMessage).orElse(this.errorMessage);
this.notPlayerMessage = notPlayerMessage;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if(!(sender instanceof Player)) {
sender.sendMessage(notPlayerMessage);
return false;
}
this.player = (Player) sender;
return super.onCommand(sender, command, label, args);
}
public Player getPlayer() {
return this.player;
}
}
}

View File

@ -0,0 +1,21 @@
package eu.mhsl.craftattack.spawn.appliance;
import eu.mhsl.craftattack.spawn.Main;
import org.bukkit.event.Listener;
/**
* Utility class which provides a specific, type save appliance.
* You can access the appliance with the protected 'appliance' field.
* @param <T> the type of your appliance
*/
public abstract class ApplianceListener<T extends Appliance> implements ApplianceSupplier<T>, Listener {
private final T appliance;
protected ApplianceListener() {
this.appliance = Main.instance().getAppliance(Main.getApplianceType(getClass()));
}
@Override
public T getAppliance() {
return appliance;
}
}

View File

@ -0,0 +1,5 @@
package eu.mhsl.craftattack.spawn.appliance;
public interface ApplianceSupplier<T extends Appliance> {
T getAppliance();
}

View File

@ -0,0 +1,15 @@
package eu.mhsl.craftattack.spawn.appliances.adminMarker;
import eu.mhsl.craftattack.spawn.appliance.Appliance;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class AdminMarker extends Appliance {
@Override
protected @NotNull List<Listener> eventHandlers() {
return List.of(new AdminMarkerListener());
}
}

View File

@ -0,0 +1,24 @@
package eu.mhsl.craftattack.spawn.appliances.adminMarker;
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
import net.kyori.adventure.text.format.TextColor;
import org.bukkit.Color;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent;
public class AdminMarkerListener extends ApplianceListener<AdminMarker> {
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player p = event.getPlayer();
p.displayName(p.displayName().color(getPlayerColor(p)));
p.playerListName(p.playerListName().color(getPlayerColor(p)));
}
private TextColor getPlayerColor(Player player) {
if (player.hasPermission("chatcolor")) return TextColor.color(Color.AQUA.asRGB()); // TODO read permission from config
return TextColor.color(Color.WHITE.asRGB());
}
}

View File

@ -0,0 +1,14 @@
package eu.mhsl.craftattack.spawn.appliances.chatMessages;
import eu.mhsl.craftattack.spawn.appliance.Appliance;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class ChatMessages extends Appliance {
@Override
protected @NotNull List<Listener> eventHandlers() {
return List.of(new ChatMessagesListener());
}
}

View File

@ -0,0 +1,70 @@
package eu.mhsl.craftattack.spawn.appliances.chatMessages;
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
import io.papermc.paper.event.player.AsyncChatEvent;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
import org.bukkit.Color;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.Optional;
public class ChatMessagesListener extends ApplianceListener<ChatMessages> {
@EventHandler
public void onPlayerChatEvent(AsyncChatEvent event) {
event.renderer(
(source, sourceDisplayName, message, viewer) ->
Component.text("")
.append(getReportablePlayerName(source))
.append(Component.text(" > ").color(TextColor.color(Color.GRAY.asRGB())))
.append(message).color(TextColor.color(Color.SILVER.asRGB()))
);
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
event.joinMessage(
Component
.text(">>> ").color(NamedTextColor.GREEN)
.append(getReportablePlayerName(event.getPlayer()))
);
}
@EventHandler
public void onPlayerLeave(PlayerQuitEvent event) {
event.quitMessage(
Component
.text("<<< ").color(NamedTextColor.RED)
.append(getReportablePlayerName(event.getPlayer()))
);
}
@EventHandler
public void onDeath(PlayerDeathEvent event) {
event.deathMessage(
Component
.text("")
.append(
Optional
.ofNullable(event.deathMessage())
.orElse(Component.text(event.getPlayer().getName()))
)
.color(TextColor.color(Color.SILVER.asRGB()))
);
}
private Component getReportablePlayerName(Player player) {
return Component
.text("")
.append(player.displayName())
.hoverEvent(HoverEvent.showText(Component.text("Klicke, um diesen Spieler zu reporten").color(NamedTextColor.GOLD)))
.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/report " + player.getName() + " "));
}
}

View File

@ -0,0 +1,103 @@
package eu.mhsl.craftattack.spawn.appliances.countdown;
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.countdown.command.ProjectStartCancelCommand;
import eu.mhsl.craftattack.spawn.appliances.countdown.command.ProjectStartCommand;
import eu.mhsl.craftattack.spawn.appliances.countdown.command.ProjectStartResetCommand;
import eu.mhsl.craftattack.spawn.appliances.countdown.listener.PlayerInvincibleListener;
import eu.mhsl.craftattack.spawn.config.Configuration;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
import org.bukkit.WorldBorder;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.function.Consumer;
public class Countdown extends Appliance {
public Countdown() {
super("countdown");
}
private int taskId = -1;
private boolean isRunning = false;
private int countDown;
public void startCountdown() {
if(!isEnabled()) return;
if(isRunning) return;
this.countDown = localConfig().getInt("countdown");
this.isRunning = true;
this.taskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(Main.instance(), () -> {
if(this.countDown <= 0) {
this.cancelCountdown();
this.projectStart();
}
Bukkit.getOnlinePlayers().forEach(player -> player.sendMessage("Sekunden:" + this.countDown));
this.countDown--;
}, 20, 20);
}
public void cancelCountdown() {
if(taskId == -1) return;
Bukkit.getScheduler().cancelTask(this.taskId);
this.isRunning = false;
this.restoreBeforeStart();
}
public boolean isEnabled() {
return localConfig().getBoolean("enabled");
}
public void setEnabled(boolean enabled) {
localConfig().set("enabled", enabled);
Configuration.saveChanges();
}
public void projectStart() {
setEnabled(false);
worldBorderModifier(worldBorder -> worldBorder.setSize(worldBorder.getMaxSize()));
Bukkit.getOnlinePlayers().forEach(player -> {
player.setFoodLevel(20);
player.setHealth(20);
player.playerListName(player.playerListName().color(NamedTextColor.AQUA));
});
}
public void restoreBeforeStart() {
setEnabled(true);
worldBorderModifier(worldBorder -> {
worldBorder.setSize(localConfig().getLong("worldborder-before"));
worldBorder.setWarningDistance(0);
worldBorder.setDamageAmount(0);
});
}
private void worldBorderModifier(Consumer<WorldBorder> worldBorder) {
Bukkit.getWorlds().forEach(world -> worldBorder.accept(world.getWorldBorder()));
}
public boolean isRunning() {
return isRunning;
}
@Override
protected @NotNull List<Listener> eventHandlers() {
return List.of(new PlayerInvincibleListener());
}
@Override
protected @NotNull List<ApplianceCommand<?>> commands() {
return List.of(
new ProjectStartCommand(),
new ProjectStartCancelCommand(),
new ProjectStartResetCommand()
);
}
}

View File

@ -0,0 +1,25 @@
package eu.mhsl.craftattack.spawn.appliances.countdown.command;
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
import eu.mhsl.craftattack.spawn.appliances.countdown.Countdown;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class ProjectStartCancelCommand extends ApplianceCommand<Countdown> {
public ProjectStartCancelCommand() {
super("projectStartCancel");
}
@Override
protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if(getAppliance().isRunning()) {
getAppliance().cancelCountdown();
sender.sendMessage(Component.text("Countdown cancelled successfully!").color(NamedTextColor.GREEN));
} else {
sender.sendMessage(Component.text("Countdown is not running!").color(NamedTextColor.RED));
}
}
}

View File

@ -0,0 +1,30 @@
package eu.mhsl.craftattack.spawn.appliances.countdown.command;
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
import eu.mhsl.craftattack.spawn.appliances.countdown.Countdown;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class ProjectStartCommand extends ApplianceCommand<Countdown> {
public ProjectStartCommand() {
super("projectStart");
}
@Override
protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if(!getAppliance().isEnabled()) {
sender.sendMessage(Component.text("Countdown not enabled or executed once before!").color(NamedTextColor.RED));
return;
}
if(getAppliance().isRunning()) {
sender.sendMessage(Component.text("Countdown already running!").color(NamedTextColor.RED));
return;
}
getAppliance().startCountdown();
}
}

View File

@ -0,0 +1,18 @@
package eu.mhsl.craftattack.spawn.appliances.countdown.command;
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
import eu.mhsl.craftattack.spawn.appliances.countdown.Countdown;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class ProjectStartResetCommand extends ApplianceCommand<Countdown> {
public ProjectStartResetCommand() {
super("projectStartReset");
}
@Override
protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
getAppliance().restoreBeforeStart();
}
}

View File

@ -0,0 +1,26 @@
package eu.mhsl.craftattack.spawn.appliances.countdown.listener;
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
import eu.mhsl.craftattack.spawn.appliances.countdown.Countdown;
import io.papermc.paper.event.player.PrePlayerAttackEntityEvent;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.FoodLevelChangeEvent;
public class PlayerInvincibleListener extends ApplianceListener<Countdown> {
@EventHandler
public void onDamage(EntityDamageEvent event) {
if(event.getEntity() instanceof Player) event.setCancelled(getAppliance().isEnabled());
}
@EventHandler
public void onHunger(FoodLevelChangeEvent event) {
event.setCancelled(getAppliance().isEnabled());
}
@EventHandler
public void onHit(PrePlayerAttackEntityEvent event) {
event.setCancelled(getAppliance().isEnabled());
}
}

View File

@ -0,0 +1,65 @@
package eu.mhsl.craftattack.spawn.appliances.tablist;
import eu.mhsl.craftattack.spawn.Main;
import eu.mhsl.craftattack.spawn.appliance.Appliance;
import eu.mhsl.craftattack.spawn.util.ComponentUtil;
import eu.mhsl.craftattack.spawn.util.RainbowComponent;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.util.Ticks;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class Tablist extends Appliance {
private final int refreshRate = Ticks.TICKS_PER_SECOND * 3;
private final RainbowComponent serverName = new RainbowComponent(" CraftAttack 6 ", 7, 3);
private final Component hostName = Component.text("mhsl.eu").color(NamedTextColor.GOLD);
@Override
public void onEnable() {
Runnable updateAll = () -> Bukkit.getOnlinePlayers().forEach(this::update);
Bukkit.getScheduler().runTaskTimerAsynchronously(Main.instance(), updateAll, refreshRate, refreshRate);
}
public void update(Player player) {
updateHeader(player);
updateFooter(player);
}
public void updateHeader(Player player) {
player.sendPlayerListHeader(
Component.newline()
.append(serverName.getRainbowState())
.appendNewline()
.append(hostName)
.appendNewline()
.appendNewline()
.append(ComponentUtil.getFormattedMSPT())
.appendNewline()
.appendNewline()
.append(ComponentUtil.getFormattedPing(player))
.appendNewline()
);
}
public void updateFooter(Player player) {
player.sendPlayerListFooter(
Component.text()
.appendNewline()
.append(Component.text(" Um einen Spieler zu melden, verwende ", NamedTextColor.GRAY))
.appendNewline()
.append(Component.text("/report <spieler> <grund>", NamedTextColor.GOLD))
.appendNewline()
);
}
@Override
protected @NotNull List<Listener> eventHandlers() {
return List.of(new TablistListener());
}
}

View File

@ -0,0 +1,12 @@
package eu.mhsl.craftattack.spawn.appliances.tablist;
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent;
public class TablistListener extends ApplianceListener<Tablist> {
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
getAppliance().update(event.getPlayer());
}
}

View File

@ -0,0 +1,16 @@
package eu.mhsl.craftattack.spawn.appliances.titleClear;
import eu.mhsl.craftattack.spawn.appliance.Appliance;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class TitleClear extends Appliance {
@Override
protected @NotNull List<Listener> eventHandlers() {
return List.of(
new TitleClearListener()
);
}
}

View File

@ -0,0 +1,12 @@
package eu.mhsl.craftattack.spawn.appliances.titleClear;
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent;
public class TitleClearListener extends ApplianceListener<TitleClear> {
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
event.getPlayer().resetTitle();
}
}

View File

@ -0,0 +1,95 @@
package eu.mhsl.craftattack.spawn.appliances.worldmuseum;
import eu.mhsl.craftattack.spawn.appliance.Appliance;
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
import eu.mhsl.craftattack.spawn.appliances.worldmuseum.listener.InventoryOpenListener;
import eu.mhsl.craftattack.spawn.config.ConfigUtil;
import eu.mhsl.craftattack.spawn.config.Configuration;
import eu.mhsl.craftattack.spawn.appliances.worldmuseum.command.MoveWorldMuseumVillagerCommand;
import eu.mhsl.craftattack.spawn.appliances.worldmuseum.listener.PlayerEntityInteractListener;
import eu.mhsl.craftattack.spawn.util.ChunkUtils;
import eu.mhsl.craftattack.spawn.util.PluginMessage;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.*;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
public class WorldMuseum extends Appliance {
public Villager villager;
public WorldMuseum() {
super("worldMuseum");
}
@Override
public void onEnable() {
// sadly, already existing entities can only be found when chunks are loaded, so to reuse the villager, the chunk has to be loaded
// https://www.spigotmc.org/threads/getting-entity-problem.332246/
Location location = ConfigUtil.Position.paseLocation(Objects.requireNonNull(localConfig().getConfigurationSection("villagerLocation")));
try {
UUID villagerUuid = UUID.fromString(Objects.requireNonNull(localConfig().getString("uuid")));
ChunkUtils.loadChunkAtLocation(location);
this.villager = (Villager) Objects.requireNonNull(Bukkit.getWorld("world")).getEntity(villagerUuid);
Objects.requireNonNull(this.villager);
} catch (NullPointerException | IllegalArgumentException e) {
this.villager = createVillagerEntity();
}
this.villager.teleport(location);
}
public void updateVillagerPosition(Location location) {
ConfigUtil.Position.writeLocation(
Objects.requireNonNull(localConfig().getConfigurationSection("villagerLocation")),
location
);
Configuration.saveChanges();
this.villager.teleport(location);
}
public void handleVillagerInteraction(Player player) {
Bukkit.getLogger().info("Sending" + player.getName() + " to WorldMuseum");
PluginMessage.connect(player, localConfig().getString("connect-server-name"));
}
private Villager createVillagerEntity() {
Location villagerLocation = ConfigUtil.Position.paseLocation(Objects.requireNonNull(localConfig().getConfigurationSection("villagerLocation")));
Villager villager = (Villager) villagerLocation.getWorld().spawnEntity(villagerLocation, EntityType.VILLAGER);
localConfig().set("uuid", villager.getUniqueId().toString());
Configuration.saveChanges();
villager.setInvulnerable(true);
villager.setPersistent(true);
villager.setGravity(false);
villager.setAI(false);
villager.setCollidable(false);
villager.setCustomNameVisible(true);
villager.customName(Component.text("Weltenansicht").color(NamedTextColor.GOLD));
villager.setProfession(Villager.Profession.LIBRARIAN);
villager.setVillagerType(Villager.Type.SAVANNA);
return villager;
}
@Override
protected @NotNull List<ApplianceCommand<?>> commands() {
return List.of(new MoveWorldMuseumVillagerCommand());
}
@Override
protected @NotNull List<Listener> eventHandlers() {
return List.of(
new PlayerEntityInteractListener(),
new InventoryOpenListener()
);
}
}

View File

@ -0,0 +1,18 @@
package eu.mhsl.craftattack.spawn.appliances.worldmuseum.command;
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
import eu.mhsl.craftattack.spawn.appliances.worldmuseum.WorldMuseum;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class MoveWorldMuseumVillagerCommand extends ApplianceCommand.PlayerChecked<WorldMuseum> {
public MoveWorldMuseumVillagerCommand() {
super("moveWorldMuseumVillager");
}
@Override
protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
getAppliance().updateVillagerPosition(getPlayer().getLocation());
}
}

View File

@ -0,0 +1,16 @@
package eu.mhsl.craftattack.spawn.appliances.worldmuseum.listener;
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
import eu.mhsl.craftattack.spawn.appliances.worldmuseum.WorldMuseum;
import org.bukkit.entity.Villager;
import org.bukkit.event.EventHandler;
import org.bukkit.event.inventory.InventoryOpenEvent;
public class InventoryOpenListener extends ApplianceListener<WorldMuseum> {
@EventHandler
public void onInventoryOpen(InventoryOpenEvent event) {
if(event.getInventory().getHolder() instanceof Villager villager) {
event.setCancelled(villager.getUniqueId().equals(getAppliance().villager.getUniqueId()));
}
}
}

View File

@ -0,0 +1,16 @@
package eu.mhsl.craftattack.spawn.appliances.worldmuseum.listener;
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
import eu.mhsl.craftattack.spawn.appliances.worldmuseum.WorldMuseum;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
public class PlayerEntityInteractListener extends ApplianceListener<WorldMuseum> {
@EventHandler
public void onInteract(PlayerInteractAtEntityEvent event) {
if (!event.getRightClicked().getUniqueId().equals(getAppliance().villager.getUniqueId())) return;
event.setCancelled(true);
getAppliance().handleVillagerInteraction(event.getPlayer());
}
}

View File

@ -1,16 +0,0 @@
package eu.mhsl.craftattack.spawn.chatMessages;
import eu.mhsl.craftattack.spawn.Main;
import eu.mhsl.craftattack.spawn.chatMessages.listeners.PlayerChatListener;
import org.bukkit.Bukkit;
public class ChatMessagesMain {
public static void onEnable() {
Main main = Main.getInstance();
Bukkit.getPluginManager().registerEvents(new PlayerChatListener(), main);
}
public static void onDisable() {
}
}

View File

@ -1,82 +0,0 @@
package eu.mhsl.craftattack.spawn.chatMessages.listeners;
import eu.mhsl.craftattack.spawn.util.ConfigUtil;
import io.papermc.paper.event.player.AsyncChatEvent;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.format.TextColor;
import org.bukkit.Color;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.Objects;
import com.theokanning.openai.completion.CompletionRequest;
import com.theokanning.openai.service.OpenAiService;
public class PlayerChatListener implements Listener {
@EventHandler
public void onPlayerChatEvent(AsyncChatEvent event) {
event.renderer(
(source, sourceDisplayName, message, viewer) -> Component.text("")
.append(sourceDisplayName.color(getPlayerColor(source)).clickEvent(ClickEvent.clickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/report " + source.getName())))
.append(Component.text(" > ").color(TextColor.color(Color.GRAY.asRGB())))
.append(message).color(TextColor.color(Color.SILVER.asRGB())));
if (ConfigUtil.getConfigUtil().isApiSwearWordCheck()) checkForSwearWord(((TextComponent) event.message()).content());
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
event.joinMessage(
Component.text("")
.append(Component.text("").color(TextColor.color(Color.GREEN.asRGB())))
.append(Component.text(event.getPlayer().getName()).color(getPlayerColor(event.getPlayer())))
);
}
@EventHandler
public void onPlayerLeave(PlayerQuitEvent event) {
event.quitMessage(
Component.text("")
.append(Component.text("").color(TextColor.fromCSSHexString("#8C0012")))
.append(Component.text(event.getPlayer().getName()).color(getPlayerColor(event.getPlayer())))
);
}
@EventHandler
public void onDeath(PlayerDeathEvent event) {
event.deathMessage(Component.text("").append(Objects.requireNonNull(event.deathMessage()).color(TextColor.color(Color.SILVER.asRGB()))));
}
private TextColor getPlayerColor(Player player) {
if (player.hasPermission("chatcolor")) return TextColor.color(Color.AQUA.asRGB());
return TextColor.color(Color.WHITE.asRGB());
}
private boolean checkForSwearWord(String msg) {
String token = ConfigUtil.getConfigUtil().getApiToken();
OpenAiService service = new OpenAiService(token);
CompletionRequest completionRequest = CompletionRequest.builder()
.prompt("Does \"" + msg + "\" contain a swear word or ist it maybe insulting to another player? Only answer with true of false!")
.model("text-davinci-003")
.temperature(0D)
.maxTokens(4)
.topP(1D)
.frequencyPenalty(0.5D)
.presencePenalty(0D)
.bestOf(1)
.build();
System.out.println(service.createCompletion(completionRequest).getChoices().get(0).getText());
// Report if necessary is needed
return false;
}
}

View File

@ -0,0 +1,31 @@
package eu.mhsl.craftattack.spawn.config;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import java.util.Optional;
public class ConfigUtil {
public static class Position {
public static Location paseLocation(ConfigurationSection section) {
return new Location(
Bukkit.getWorld(Optional.ofNullable(section.getString("world")).orElse("world")),
section.getDouble("x"),
section.getDouble("y"),
section.getDouble("z"),
(float) section.getDouble("yaw"),
(float) section.getDouble("pitch")
);
}
public static void writeLocation(ConfigurationSection section, Location location) {
section.set("world", location.getWorld().getName());
section.set("x", location.x());
section.set("y", location.y());
section.set("z", location.z());
section.set("yaw", location.getYaw());
section.set("pitch", location.getPitch());
}
}
}

View File

@ -0,0 +1,27 @@
package eu.mhsl.craftattack.spawn.config;
import eu.mhsl.craftattack.spawn.Main;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
public class Configuration {
private static final String configName = "config.yml";
private static final File configFile = new File(Main.instance().getDataFolder().getAbsolutePath() + "/" + configName);
public static FileConfiguration cfg;
public static void readConfig() {
cfg = YamlConfiguration.loadConfiguration(configFile);
}
public static void saveChanges() {
try {
cfg.save(configFile);
} catch (Exception e) {
Bukkit.getLogger().warning("Could not save configuration: " + e.getMessage());
}
}
}

View File

@ -0,0 +1,22 @@
package eu.mhsl.craftattack.spawn.util;
import org.bukkit.Chunk;
import org.bukkit.Location;
public class ChunkUtils {
public record ChunkPos(int x, int z) {}
public static Chunk loadChunkAtLocation(Location location) {
ChunkPos chunkPos = locationToChunk(location);
return location.getWorld().getChunkAt(chunkPos.x, chunkPos.z);
}
public static ChunkPos locationToChunk(Location location) {
return new ChunkPos(floor(location.x()) >> 4, floor(location.z()) >> 4);
}
private static int floor(double num) {
int floor = (int) num;
return floor == num ? floor : floor - (int) (Double.doubleToRawLongBits(num) >>> 63);
}
}

View File

@ -0,0 +1,18 @@
package eu.mhsl.craftattack.spawn.util;
import net.kyori.adventure.text.format.TextColor;
import java.awt.*;
public class ColorUtil {
public static TextColor mapGreenToRed(double value, double minValue, double maxValue, boolean lowIsGreen) {
float hue = (float) NumberUtil.map(value, minValue, maxValue, 0, 120);
if(lowIsGreen) {
hue = Math.abs(hue - 120);
}
System.out.println("hue " + hue);
return TextColor.color(Color.getHSBColor(hue/360, 1f, 1f).getRGB());
}
}

View File

@ -0,0 +1,80 @@
package eu.mhsl.craftattack.spawn.util;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.awt.*;
import java.util.Arrays;
public class ComponentUtil {
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 getFormattedMSPT() {
long[] times = Bukkit.getServer().getTickTimes();
double mspt = ((double) Arrays.stream(times).sum() / (double) times.length) * 1.0E-6D;
double roundedMspt = (double) Math.round(mspt * 100d) / 100d;
int percentage = (int) (Math.min(100, (mspt / 50.0) * 100));
TextColor msptColor = ColorUtil.mapGreenToRed(roundedMspt, 0, 50, true);
TextColor percentageColor = ColorUtil.mapGreenToRed(mspt, 90, 100, true);
return Component.text()
.append(Component.text("Serverlast: ", NamedTextColor.GRAY))
.append(Component.text(percentage + "% ", percentageColor))
.appendNewline()
.append(Component.text("(", NamedTextColor.GRAY))
.append(Component.text(roundedMspt + "ms", msptColor))
.append(Component.text(" per tick)", NamedTextColor.GRAY))
.build();
}
public static Component getFormattedPing(Player player) {
return Component.text()
.append(Component.text("Dein Ping: ", NamedTextColor.GRAY))
.append(Component.text(player.getPing() + "ms", ColorUtil.mapGreenToRed(player.getPing(), 100, 500, true)))
.build();
}
public static Component createRainbowText(String text) {
Component builder = Component.empty();
int hue = 0;
for (char c : text.toCharArray()) {
TextColor color = TextColor.color(Color.getHSBColor((float) hue / 360, 1, 1).getRGB());
builder = builder.append(Component.text(c).color(color));
hue += 30;
}
return builder;
}
}

View File

@ -1,80 +0,0 @@
package eu.mhsl.craftattack.spawn.util;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.util.List;
import java.util.Objects;
public class ConfigUtil {
private static ConfigUtil instance;
private final File file;
private final FileConfiguration config;
//loaded config variables
private boolean apiSwearWordCheck = false;
private String apiToken;
public static ConfigUtil getConfigUtil() {
if (instance == null) instance = new ConfigUtil("config.yml");
return instance;
}
private ConfigUtil(String path) {
this.file = new File(Objects.requireNonNull(Bukkit.getPluginManager().getPlugin("spawn")).getDataFolder().getAbsolutePath() + "/" + path);
this.config = YamlConfiguration.loadConfiguration(this.file);
loadConfig();
}
public boolean save() {
try {
this.config.save(this.file);
return true;
}catch (Exception e) {
e.printStackTrace();
return false;
}
}
private void loadConfig() {
apiSwearWordCheck = (boolean) config.get("enableSwearWordCheck");
apiToken = (String) config.get("apiToken");
}
public FileConfiguration getConfig() {
return this.config;
}
public Location getVillagerLocation() {
List<Double> cordsList = this.config.getDoubleList("villagerLocation");
World world = Bukkit.getWorld("world");
double x = cordsList.get(0);
double y = cordsList.get(1);
double z = cordsList.get(2);
double yaw = cordsList.get(3);
double pitch = cordsList.get(4);
Location location = new Location(world, x, y, z);
location.setYaw((float) yaw);
location.setPitch((float) pitch);
return location;
}
public Location getSpawnLocation() {
List<Double> cordsList = this.config.getDoubleList("spawnLocation");
World world = Bukkit.getWorld("world");
double x = cordsList.get(0);
double y = cordsList.get(1);
double z = cordsList.get(2);
return new Location(world, x, y, z);
}
public boolean isApiSwearWordCheck() {
return apiSwearWordCheck;
}
public String getApiToken() {
return apiToken;
}
}

View File

@ -0,0 +1,11 @@
package eu.mhsl.craftattack.spawn.util;
public class NumberUtil {
public static double map(double oldValue, double oldMin, double oldMax, double newMin, double newMax) {
double out = (((oldValue - oldMin) * (newMax - newMin)) / (oldMax - oldMin)) + newMin;
if(out > newMax) out = newMax;
if(out < newMin) out = newMin;
return out;
}
}

View File

@ -1,17 +1,15 @@
package eu.mhsl.craftattack.spawn.worldmuseum.util; package eu.mhsl.craftattack.spawn.util;
import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import eu.mhsl.craftattack.spawn.Main; import eu.mhsl.craftattack.spawn.Main;
import eu.mhsl.craftattack.spawn.worldmuseum.WorldMueseumMain;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
public class PluginMessage { public class PluginMessage {
private final Main plugin = WorldMueseumMain.getInstance(); public static void connect(Player player, String server) {
public void connect(Player player, String server) {
ByteArrayDataOutput output = ByteStreams.newDataOutput(); ByteArrayDataOutput output = ByteStreams.newDataOutput();
output.writeUTF("Connect"); output.writeUTF("Connect");
output.writeUTF(server); output.writeUTF(server);
player.sendPluginMessage(plugin, "BungeeCord", output.toByteArray()); player.sendPluginMessage(Main.instance(), "BungeeCord", output.toByteArray());
} }
} }

View File

@ -0,0 +1,33 @@
package eu.mhsl.craftattack.spawn.util;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor;
import java.awt.*;
public class RainbowComponent {
private int hueOffset = 0;
private final String text;
private final int density;
private final int speed;
public RainbowComponent(String text, int density, int speed) {
this.text = text;
this.density = density;
this.speed = speed;
}
public Component getRainbowState() {
Component builder = Component.empty();
int hue = this.hueOffset;
for (char c : text.toCharArray()) {
TextColor color = TextColor.color(Color.getHSBColor((float) hue / 360, 1, 1).getRGB());
builder = builder.append(Component.text(c).color(color));
hue += density;
}
if(this.hueOffset > Byte.MAX_VALUE - speed) this.hueOffset = 0;
this.hueOffset += (byte) speed;
return builder;
}
}

View File

@ -1,38 +0,0 @@
package eu.mhsl.craftattack.spawn.worldmuseum;
import eu.mhsl.craftattack.spawn.Main;
import eu.mhsl.craftattack.spawn.worldmuseum.command.WorldMuseumVillagerCommand;
import eu.mhsl.craftattack.spawn.worldmuseum.listener.PlayerEntityInteractListener;
import eu.mhsl.craftattack.spawn.worldmuseum.util.VillagerSpawner;
import org.bukkit.Bukkit;
import java.util.Objects;
public class WorldMueseumMain {
public static void onEnable() {
Main main = getInstance();
VillagerSpawner.spawnVillager();
// register Messaging-Channels
main.getServer().getMessenger().registerOutgoingPluginChannel(main, "BungeeCord");
// register Commands
Objects.requireNonNull(main.getCommand("worldMuseum-villager")).setExecutor(new WorldMuseumVillagerCommand());
// register listeners
Bukkit.getPluginManager().registerEvents(new PlayerEntityInteractListener(), main);
}
public static void onDisable() {
VillagerSpawner.killVillager();
}
public static Main getInstance() {
return Main.getInstance();
}
}

View File

@ -1,41 +0,0 @@
package eu.mhsl.craftattack.spawn.worldmuseum.command;
import eu.mhsl.craftattack.spawn.util.ConfigUtil;
import eu.mhsl.craftattack.spawn.worldmuseum.util.VillagerSpawner;
import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.*;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class WorldMuseumVillagerCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player player)) return false;
Location playerLocation = player.getLocation();
double x = playerLocation.getX();
double y = playerLocation.getY();
double z = playerLocation.getZ();
double yaw = playerLocation.getYaw();
double pitch = playerLocation.getPitch();
List<Double> cordList = new ArrayList<>() {
{
add(x);
add(y);
add(z);
add(yaw);
add(pitch);
}
};
ConfigUtil.getConfigUtil().getConfig().set("villagerLocation", cordList);
ConfigUtil.getConfigUtil().save();
VillagerSpawner.killVillager();
VillagerSpawner.spawnVillager();
return false;
}
}

View File

@ -1,13 +0,0 @@
package eu.mhsl.craftattack.spawn.worldmuseum.listener;
import eu.mhsl.craftattack.spawn.worldmuseum.util.PlayerOnlineUtil;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
public class PlayerDisconnectListener implements Listener {
@EventHandler
public void onDisconnect(PlayerQuitEvent event) {
if (PlayerOnlineUtil.worldMuseumCheck(event.getPlayer())) PlayerOnlineUtil.remove(event.getPlayer());
}
}

View File

@ -1,25 +0,0 @@
package eu.mhsl.craftattack.spawn.worldmuseum.listener;
import eu.mhsl.craftattack.spawn.util.ConfigUtil;
import eu.mhsl.craftattack.spawn.worldmuseum.util.PlayerOnlineUtil;
import eu.mhsl.craftattack.spawn.worldmuseum.util.PluginMessage;
import eu.mhsl.craftattack.spawn.worldmuseum.util.VillagerSpawner;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
public class PlayerEntityInteractListener implements Listener {
private final PluginMessage pluginMessage = new PluginMessage();
@EventHandler
public void onInteract(PlayerInteractAtEntityEvent event) {
if (!event.getRightClicked().equals(VillagerSpawner.getStaticVillager())) return;
event.setCancelled(true);
if (PlayerOnlineUtil.worldMuseumCheck(event.getPlayer())) return;
String servername = ConfigUtil.getConfigUtil().getConfig().getString("world-museum-name");
pluginMessage.connect(event.getPlayer(), servername);
PlayerOnlineUtil.addPlayer(event.getPlayer());
Bukkit.getLogger().info(event.getPlayer().getName() + " connects to Worldmuseum");
}
}

View File

@ -1,20 +0,0 @@
package eu.mhsl.craftattack.spawn.worldmuseum.util;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
public class PlayerOnlineUtil {
private static final List<Player> playerOnWorldMuseum= new ArrayList<>(); // if player is in list --> he will be connected to worldmuseum
public static void addPlayer(Player player) {
playerOnWorldMuseum.add(player);
}
public static boolean worldMuseumCheck(Player player) {
return playerOnWorldMuseum.contains(player);
}
public static void remove(Player player) {
playerOnWorldMuseum.remove(player);
}
}

View File

@ -1,33 +0,0 @@
package eu.mhsl.craftattack.spawn.worldmuseum.util;
import eu.mhsl.craftattack.spawn.util.ConfigUtil;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Villager;
public class VillagerSpawner {
private static Villager staticVillager;
public static void spawnVillager() {
ConfigUtil config = ConfigUtil.getConfigUtil();
Location location = config.getVillagerLocation();
assert EntityType.VILLAGER.getEntityClass() != null;
Villager villager = (Villager) location.getWorld().spawn(location, EntityType.VILLAGER.getEntityClass());
villager.setAI(false);
villager.setInvulnerable(true);
villager.setSilent(true);
villager.setCollidable(false);
villager.setRemoveWhenFarAway(false);
villager.setProfession(Villager.Profession.LIBRARIAN);
staticVillager = villager;
}
public static void killVillager() {
staticVillager.remove();
}
public static Villager getStaticVillager() {
return staticVillager;
}
}

View File

@ -1,21 +1,22 @@
# Worldmuseum worldMuseum:
enableWorldMuseum: false enabled: false
villagerLocation: uuid:
- 0 #x connect-server-name: worldmuseum
- 0 #y villagerLocation:
- 0 #z world: world
- 0 #yaw x: 0
- 0 #pitch y: 0
world-museum-name: worldmuseum z: 0
yaw: 0
pitch: 0
# ChatMessages adminMarker:
enableChatMessageOverrides: false permission: admin
enableSwearWordCheck: false color: AQUA
apiToken:
# Porjectstart countdown:
enableProjectstart: false enabled: false
spawnLocation: start-permission: admin
- 0 #x countdown: 60
- 0 #y worldborder-before: 37
- 0 #z worldborder-after: 0

View File

@ -1,7 +0,0 @@
name: spawn
version: 1.0
main: eu.mhsl.craftattack.spawn.Main
api-version: 1.19
commands:
spawnWorldMuseumVillager:
description: Spawns Worldmuseum-villager

View File

@ -1,8 +1,16 @@
name: spawn name: spawn
version: 1.0 author: olischma, muelleel
version: '1.0'
main: eu.mhsl.craftattack.spawn.Main main: eu.mhsl.craftattack.spawn.Main
api-version: 1.19 api-version: '1.20'
commands: commands:
worldMuseum-villager: moveWorldMuseumVillager:
description: updates Worldmuseum-villager to current player location description: Moves world museum villager to current player location and persists location to config
usage: /worldMuseum-villager usage: /moveWmVillager
permission: admin
projectStart:
description: Starts project countdown
projectStartCancel:
description: Cancels project countdown
projectStartReset:
description: Resets project countdown