/* * This file is a part of the SteamWar software. * * Copyright (C) 2021 SteamWar.de-Serverteam * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package de.steamwar.bausystem; import com.comphenix.tinyprotocol.TinyProtocol; import de.steamwar.bausystem.config.BauServer; import de.steamwar.bausystem.configplayer.Config; import de.steamwar.bausystem.configplayer.ConfigConverter; import de.steamwar.bausystem.features.gui.BauGUI; import de.steamwar.bausystem.features.script.lua.SteamWarLuaPlugin; import de.steamwar.bausystem.features.script.lua.libs.LuaLib; import de.steamwar.bausystem.features.slaves.panzern.Panzern; import de.steamwar.bausystem.features.slaves.panzern.PanzernAlgorithm; import de.steamwar.bausystem.features.tpslimit.TPSFreezeUtils; import de.steamwar.bausystem.features.world.BauScoreboard; import de.steamwar.bausystem.linkage.specific.BauGuiItem; import de.steamwar.bausystem.region.loader.PrototypeLoader; import de.steamwar.bausystem.region.loader.RegionLoader; import de.steamwar.bausystem.region.loader.Updater; import de.steamwar.bausystem.utils.ScoreboardElement; import de.steamwar.bausystem.utils.TickListener; import de.steamwar.bausystem.worlddata.WorldData; import de.steamwar.command.AbstractValidator; import de.steamwar.command.SWCommand; import de.steamwar.command.SWCommandUtils; import de.steamwar.core.Core; import de.steamwar.linkage.*; import de.steamwar.linkage.api.Disable; import de.steamwar.linkage.api.Enable; import de.steamwar.message.Message; import de.steamwar.network.packets.PacketHandler; import lombok.Getter; import org.atteo.classindex.ClassIndex; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; import java.io.*; import java.lang.reflect.Field; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.logging.Level; import java.util.stream.Collectors; public class BauSystem extends JavaPlugin implements Listener { // This should be treated as final! public static Message MESSAGE; public static final boolean DEV_SERVER = !System.getProperty("user.home").endsWith("minecraft"); @Getter private static BauSystem instance; private final Map, Object> instances = new HashMap<>(); @Override public void onEnable() { // LOGGER fixLogging(); MESSAGE = new Message("BauSystem", getClassLoader()); instance = this; SWUtils.setBausystem(instance); try { PrototypeLoader.load(); RegionLoader.load(); } catch (SecurityException e) { Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e); Bukkit.shutdown(); System.exit(1); return; } new Updater(PrototypeLoader.file, PrototypeLoader::load); new Updater(RegionLoader.file, RegionLoader::load); SWCommandUtils.addValidator(Player.class, validator(Permission.BUILD)); SWCommandUtils.addValidator(CommandSender.class, validator(Permission.BUILD)); SWCommandUtils.addValidator("supervisor", validator(Permission.SUPERVISOR)); SWCommandUtils.addValidator("owner", validator(Permission.OWNER)); instances.put(BauServer.class, BauServer.getInstance()); List> classes = new BufferedReader(new InputStreamReader(BauSystem.class.getResourceAsStream("/META-INF/annotations/de.steamwar.linkage.Linked"))) .lines() .map(s -> { try { return Class.forName(s); } catch (ClassNotFoundException e) { return null; } }) .filter(Objects::nonNull) .collect(Collectors.toList()); classes.forEach(clazz -> { try { Object any = clazz.newInstance(); MinVersion minVersion = clazz.getAnnotation(MinVersion.class); MaxVersion maxVersion = clazz.getAnnotation(MaxVersion.class); PluginCheck[] pluginChecks = clazz.getAnnotationsByType(PluginCheck.class); if (minVersion != null && Core.getVersion() < minVersion.value()) { return; } if (maxVersion != null && Core.getVersion() > maxVersion.value()) { return; } for (PluginCheck pluginCheck : pluginChecks) { if (pluginCheck.has() == PluginCheck.Has.THIS && Bukkit.getPluginManager().getPlugin(pluginCheck.value()) != null) { continue; } if (pluginCheck.has() == PluginCheck.Has.NOT && Bukkit.getPluginManager().getPlugin(pluginCheck.value()) == null) { continue; } return; } instances.put(clazz, any); if (any instanceof Enable) { ((Enable) any).enable(); } if (any instanceof SWCommand) { ((SWCommand) any).setMessage(BauSystem.MESSAGE); } if (any instanceof Listener) { Bukkit.getPluginManager().registerEvents((Listener) any, BauSystem.getInstance()); } if (any instanceof PacketHandler) { ((PacketHandler) any).register(); } if (any instanceof LuaLib) { SteamWarLuaPlugin.add((LuaLib) any); } if (any instanceof ScoreboardElement) { BauScoreboard.addElement((ScoreboardElement) any); } if (any instanceof BauGuiItem) { BauGUI.addItem((BauGuiItem) any); } if (any instanceof PanzernAlgorithm) { Panzern.add((PanzernAlgorithm) any); } if (any instanceof ConfigConverter) { Config.addConfigConverter((ConfigConverter) any); } } catch (InstantiationException | IllegalAccessException e) { Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e); } }); instances.forEach((clazz, o) -> { for (Field field : clazz.getFields()) { if (field.getAnnotation(LinkedInstance.class) != null) { try { field.set(o, instances.get(field.getType())); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } } }); TickListener.impl.init(); } @Override public void onDisable() { instances.forEach((aClass, o) -> { if (o instanceof Listener) { HandlerList.unregisterAll((Listener) o); } if (o instanceof Disable) { ((Disable) o).disable(); } }); WorldData.write(); Config.getInstance().saveAll(); TinyProtocol.instance.close(); } private AbstractValidator validator(Permission permission) { return (commandSender, object, messageSender) -> { if (commandSender instanceof Player) { if (permission.hasPermission((Player) commandSender)) { return true; } messageSender.send("NO_PERMISSION"); return false; } return true; }; } private void fixLogging() { System.setErr(new PrintStream(new OutputStream() { private StringBuilder current = new StringBuilder(); @Override public void write(int b) throws IOException { if (b == '\n') { String logging = current.toString(); if (logging.contains("SLF4J")) { Bukkit.getLogger().info(logging); } else { Bukkit.getLogger().warning(logging); } current = new StringBuilder(); } else { current.append((char) b); } } })); } public static BukkitTask runTaskLater(Plugin plugin, Runnable runnable, long delay) { return new BukkitRunnable() { private int counter = 1; @Override public void run() { if (TPSFreezeUtils.isFrozen()) return; if (counter >= delay) { runnable.run(); cancel(); return; } counter++; } }.runTaskTimer(plugin, 0, 1); } public static BukkitTask runTaskTimer(Plugin plugin, Runnable runnable, long delay, long period) { return new BukkitRunnable() { private int counter = 1; private boolean first = true; @Override public void run() { if (TPSFreezeUtils.isFrozen()) return; if (counter >= (first ? delay : period)) { first = false; runnable.run(); counter = 1; return; } counter++; } }.runTaskTimer(plugin, 0, 1); } public static void runTaskTimer(Plugin plugin, Consumer consumer, long delay, long period) { AtomicReference task = new AtomicReference<>(); task.set(runTaskTimer(plugin, () -> consumer.accept(task.get()), delay, period)); } }