Skript Diff
4 removals
Words removed | 5 |
Total words | 2526 |
Words removed (%) | 0.20 |
680 lines
3 additions
Words added | 5 |
Total words | 2526 |
Words added (%) | 0.20 |
679 lines
/**
/**
* This file is part of Skript.
* This file is part of Skript.
*
*
* Skript is free software: you can redistribute it and/or modify
* Skript is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* (at your option) any later version.
*
*
* Skript is distributed in the hope that it will be useful,
* Skript is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU General Public License
* along with Skript. If not, see <http://www.gnu.org/licenses/>.
* along with Skript. If not, see <http://www.gnu.org/licenses/>.
*
*
*
*
* Copyright 2011-2017 Peter Güttinger and contributors
* Copyright 2011-2017 Peter Güttinger and contributors
*/
*/
package ch.njol.skript;
package ch.njol.skript;
import java.io.File;
import java.io.File;
import java.io.IOException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStream;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.net.MalformedURLException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.StandardCharsets;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collection;
import java.util.Collections;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Iterator;
import java.util.List;
import java.util.List;
import java.util.Locale;
import java.util.Locale;
import java.util.Map;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Scanner;
import java.util.Set;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.Callable;
import java.util.jar.JarEntry;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarFile;
import java.util.logging.Filter;
import java.util.logging.Filter;
import java.util.logging.Level;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.LogRecord;
import java.util.regex.Matcher;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipFile;
import ch.njol.skript.lang.Trigger;
import ch.njol.skript.lang.Trigger;
import org.bukkit.Bukkit;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.server.ServerCommandEvent;
import org.bukkit.event.server.ServerCommandEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jdt.annotation.Nullable;
import com.google.gson.Gson;
import com.google.gson.Gson;
import ch.njol.skript.aliases.Aliases;
import ch.njol.skript.aliases.Aliases;
import ch.njol.skript.bukkitutil.BukkitUnsafe;
import ch.njol.skript.bukkitutil.BukkitUnsafe;
import ch.njol.skript.bukkitutil.BurgerHelper;
import ch.njol.skript.bukkitutil.BurgerHelper;
import ch.njol.skript.bukkitutil.Workarounds;
import ch.njol.skript.bukkitutil.Workarounds;
import ch.njol.skript.classes.ClassInfo;
import ch.njol.skript.classes.ClassInfo;
import ch.njol.skript.classes.Comparator;
import ch.njol.skript.classes.Comparator;
import ch.njol.skript.classes.Converter;
import ch.njol.skript.classes.Converter;
import ch.njol.skript.classes.data.BukkitClasses;
import ch.njol.skript.classes.data.BukkitClasses;
import ch.njol.skript.classes.data.BukkitEventValues;
import ch.njol.skript.classes.data.BukkitEventValues;
import ch.njol.skript.classes.data.DefaultComparators;
import ch.njol.skript.classes.data.DefaultComparators;
import ch.njol.skript.classes.data.DefaultConverters;
import ch.njol.skript.classes.data.DefaultConverters;
import ch.njol.skript.classes.data.DefaultFunctions;
import ch.njol.skript.classes.data.DefaultFunctions;
import ch.njol.skript.classes.data.JavaClasses;
import ch.njol.skript.classes.data.JavaClasses;
import ch.njol.skript.classes.data.SkriptClasses;
import ch.njol.skript.classes.data.SkriptClasses;
import ch.njol.skript.command.Commands;
import ch.njol.skript.command.Commands;
import ch.njol.skript.doc.Documentation;
import ch.njol.skript.doc.Documentation;
import ch.njol.skript.events.EvtSkript;
import ch.njol.skript.events.EvtSkript;
import ch.njol.skript.hooks.Hook;
import ch.njol.skript.hooks.Hook;
import ch.njol.skript.lang.Condition;
import ch.njol.skript.lang.Condition;
import ch.njol.skript.lang.Effect;
import ch.njol.skript.lang.Effect;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.ExpressionInfo;
import ch.njol.skript.lang.ExpressionInfo;
import ch.njol.skript.lang.ExpressionType;
import ch.njol.skript.lang.ExpressionType;
import ch.njol.skript.lang.SkriptEvent;
import ch.njol.skript.lang.SkriptEvent;
import ch.njol.skript.lang.SkriptEventInfo;
import ch.njol.skript.lang.SkriptEventInfo;
import ch.njol.skript.lang.Statement;
import ch.njol.skript.lang.Statement;
import ch.njol.skript.lang.SyntaxElementInfo;
import ch.njol.skript.lang.SyntaxElementInfo;
import ch.njol.skript.lang.TriggerItem;
import ch.njol.skript.lang.TriggerItem;
import ch.njol.skript.lang.VariableString;
import ch.njol.skript.lang.VariableString;
import ch.njol.skript.lang.function.Functions;
import ch.njol.skript.lang.function.Functions;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.skript.localization.Language;
import ch.njol.skript.localization.Language;
import ch.njol.skript.localization.Message;
import ch.njol.skript.localization.Message;
import ch.njol.skript.log.BukkitLoggerFilter;
import ch.njol.skript.log.BukkitLoggerFilter;
import ch.njol.skript.log.CountingLogHandler;
import ch.njol.skript.log.CountingLogHandler;
import ch.njol.skript.log.ErrorDescLogHandler;
import ch.njol.skript.log.ErrorDescLogHandler;
import ch.njol.skript.log.ErrorQuality;
import ch.njol.skript.log.ErrorQuality;
import ch.njol.skript.log.LogEntry;
import ch.njol.skript.log.LogEntry;
import ch.njol.skript.log.LogHandler;
import ch.njol.skript.log.LogHandler;
import ch.njol.skript.log.SkriptLogger;
import ch.njol.skript.log.SkriptLogger;
import ch.njol.skript.log.Verbosity;
import ch.njol.skript.log.Verbosity;
import ch.njol.skript.registrations.Classes;
import ch.njol.skript.registrations.Classes;
import ch.njol.skript.registrations.Comparators;
import ch.njol.skript.registrations.Comparators;
import ch.njol.skript.registrations.Converters;
import ch.njol.skript.registrations.Converters;
import ch.njol.skript.registrations.EventValues;
import ch.njol.skript.registrations.EventValues;
import ch.njol.skript.tests.runner.SkriptTestEvent;
import ch.njol.skript.tests.runner.SkriptTestEvent;
import ch.njol.skript.tests.runner.TestMode;
import ch.njol.skript.tests.runner.TestMode;
import ch.njol.skript.tests.runner.TestTracker;
import ch.njol.skript.tests.runner.TestTracker;
import ch.njol.skript.timings.SkriptTimings;
import ch.njol.skript.timings.SkriptTimings;
import ch.njol.skript.update.ReleaseManifest;
import ch.njol.skript.update.ReleaseManifest;
import ch.njol.skript.update.ReleaseStatus;
import ch.njol.skript.update.ReleaseStatus;
import ch.njol.skript.update.UpdateManifest;
import ch.njol.skript.update.UpdateManifest;
import ch.njol.skript.update.UpdaterState;
import ch.njol.skript.update.UpdaterState;
import ch.njol.skript.util.EmptyStacktraceException;
import ch.njol.skript.util.EmptyStacktraceException;
import ch.njol.skript.util.ExceptionUtils;
import ch.njol.skript.util.ExceptionUtils;
import ch.njol.skript.util.FileUtils;
import ch.njol.skript.util.FileUtils;
import ch.njol.skript.util.Getter;
import ch.njol.skript.util.Getter;
import ch.njol.skript.util.Task;
import ch.njol.skript.util.Task;
import ch.njol.skript.util.Utils;
import ch.njol.skript.util.Utils;
import ch.njol.skript.util.Version;
import ch.njol.skript.util.Version;
import ch.njol.skript.util.chat.BungeeConverter;
import ch.njol.skript.util.chat.BungeeConverter;
import ch.njol.skript.util.chat.ChatMessages;
import ch.njol.skript.util.chat.ChatMessages;
import ch.njol.skript.variables.Variables;
import ch.njol.skript.variables.Variables;
import ch.njol.util.Closeable;
import ch.njol.util.Closeable;
import ch.njol.util.Kleenean;
import ch.njol.util.Kleenean;
import ch.njol.util.NullableChecker;
import ch.njol.util.NullableChecker;
import ch.njol.util.Pair;
import ch.njol.util.Pair;
import ch.njol.util.StringUtils;
import ch.njol.util.StringUtils;
import ch.njol.util.coll.CollectionUtils;
import ch.njol.util.coll.CollectionUtils;
import ch.njol.util.coll.iterator.CheckedIterator;
import ch.njol.util.coll.iterator.CheckedIterator;
import ch.njol.util.coll.iterator.EnumerationIterable;
import ch.njol.util.coll.iterator.EnumerationIterable;
import ch.njol.util.whocalled.WhoCalled;
// TODO meaningful error if someone uses an %expression with percent signs% outside of text or a variable
// TODO meaningful error if someone uses an %expression with percent signs% outside of text or a variable
/**
/**
* <b>Skript</b> - A Bukkit plugin to modify how Minecraft behaves without having to write a single line of code (You'll likely be writing some code though if you're reading this
* <b>Skript</b> - A Bukkit plugin to modify how Minecraft behaves without having to write a single line of code (You'll likely be writing some code though if you're reading this
* =P)
* =P)
* <p>
* <p>
* Use this class to extend this plugin's functionality by adding more {@link Condition conditions}, {@link Effect effects}, {@link SimpleExpression expressions}, etc.
* Use this class to extend this plugin's functionality by adding more {@link Condition conditions}, {@link Effect effects}, {@link SimpleExpression expressions}, etc.
* <p>
* <p>
* If your plugin.yml contains <tt>'depend: [Skript]'</tt> then your plugin will not start at all if Skript is not present. Add <tt>'softdepend: [Skript]'</tt> to your plugin.yml
* If your plugin.yml contains <tt>'depend: [Skript]'</tt> then your plugin will not start at all if Skript is not present. Add <tt>'softdepend: [Skript]'</tt> to your plugin.yml
* if you want your plugin to work even if Skript isn't present, but want to make sure that Skript gets loaded before your plugin.
* if you want your plugin to work even if Skript isn't present, but want to make sure that Skript gets loaded before your plugin.
* <p>
* <p>
* If you use 'softdepend' you can test whether Skript is loaded with <tt>'Bukkit.getPluginManager().getPlugin("Skript") != null'</tt>
* If you use 'softdepend' you can test whether Skript is loaded with <tt>'Bukkit.getPluginManager().getPlugin("Skript") != null'</tt>
* <p>
* <p>
* Once you made sure that Skript is loaded you can use <code>Skript.getInstance()</code> whenever you need a reference to the plugin, but you likely won't need it since all API
* Once you made sure that Skript is loaded you can use <code>Skript.getInstance()</code> whenever you need a reference to the plugin, but you likely won't need it since all API
* methods are static.
* methods are static.
*
*
* @author Peter Güttinger
* @author Peter Güttinger
* @see #registerAddon(JavaPlugin)
* @see #registerAddon(JavaPlugin)
* @see #registerCondition(Class, String...)
* @see #registerCondition(Class, String...)
* @see #registerEffect(Class, String...)
* @see #registerEffect(Class, String...)
* @see #registerExpression(Class, Class, ExpressionType, String...)
* @see #registerExpression(Class, Class, ExpressionType, String...)
* @see #registerEvent(String, Class, Class, String...)
* @see #registerEvent(String, Class, Class, String...)
* @see EventValues#registerEventValue(Class, Class, Getter, int)
* @see EventValues#registerEventValue(Class, Class, Getter, int)
* @see Classes#registerClass(ClassInfo)
* @see Classes#registerClass(ClassInfo)
* @see Comparators#registerComparator(Class, Class, Comparator)
* @see Comparators#registerComparator(Class, Class, Comparator)
* @see Converters#registerConverter(Class, Class, Converter)
* @see Converters#registerConverter(Class, Class, Converter)
*/
*/
public final class Skript extends JavaPlugin implements Listener {
public final class Skript extends JavaPlugin implements Listener {
// ================ PLUGIN ================
// ================ PLUGIN ================
@Nullable
@Nullable
private static Skript instance = null;
private static Skript instance = null;
private static boolean disabled = false;
private static boolean disabled = false;
public static Skript getInstance() {
public static Skript getInstance() {
final Skript i = instance;
final Skript i = instance;
if (i == null)
if (i == null)
throw new IllegalStateException();
throw new IllegalStateException();
return i;
return i;
}
}
/**
/**
* Current updater instance used by Skript.
* Current updater instance used by Skript.
*/
*/
@Nullable
@Nullable
private SkriptUpdater updater;
private SkriptUpdater updater;
public Skript() throws IllegalStateException {
public Skript() throws IllegalStateException {
if (instance != null)
if (instance != null)
throw new IllegalStateException("Cannot create multiple instances of Skript!");
throw new IllegalStateException("Cannot create multiple instances of Skript!");
instance = this;
instance = this;
}
}
@Nullable
@Nullable
private static Version version = null;
private static Version version = null;
public static Version getVersion() {
public static Version getVersion() {
final Version v = version;
final Version v = version;
if (v == null)
if (v == null)
throw new IllegalStateException();
throw new IllegalStateException();
return v;
return v;
}
}
public final static Message m_invalid_reload = new Message("skript.invalid reload"),
public final static Message m_invalid_reload = new Message("skript.invalid reload"),
m_finished_loading = new Message("skript.finished loading");
m_finished_loading = new Message("skript.finished loading");
public static ServerPlatform getServerPlatform() {
public static ServerPlatform getServerPlatform() {
if (classExists("net.glowstone.GlowServer")) {
if (classExists("net.glowstone.GlowServer")) {
return ServerPlatform.BUKKIT_GLOWSTONE; // Glowstone has timings too, so must check for it first
return ServerPlatform.BUKKIT_GLOWSTONE; // Glowstone has timings too, so must check for it first
} else if (classExists("co.aikar.timings.Timings")) {
} else if (classExists("co.aikar.timings.Timings")) {
return ServerPlatform.BUKKIT_PAPER; // Could be Sponge, but it doesn't work at all at the moment
return ServerPlatform.BUKKIT_PAPER; // Could be Sponge, but it doesn't work at all at the moment
} else if (classExists("org.spigotmc.SpigotConfig")) {
} else if (classExists("org.spigotmc.SpigotConfig")) {
return ServerPlatform.BUKKIT_SPIGOT;
return ServerPlatform.BUKKIT_SPIGOT;
} else if (classExists("org.bukkit.craftbukkit.CraftServer") || classExists("org.bukkit.craftbukkit.Main")) {
} else if (classExists("org.bukkit.craftbukkit.CraftServer") || classExists("org.bukkit.craftbukkit.Main")) {
// At some point, CraftServer got removed or moved
// At some point, CraftServer got removed or moved
return ServerPlatform.BUKKIT_CRAFTBUKKIT;
return ServerPlatform.BUKKIT_CRAFTBUKKIT;
} else { // Probably some ancient Bukkit implementation
} else { // Probably some ancient Bukkit implementation
return ServerPlatform.BUKKIT_UNKNOWN;
return ServerPlatform.BUKKIT_UNKNOWN;
}
}
}
}
/**
/**
* Checks if server software and Minecraft version are supported.
* Checks if server software and Minecraft version are supported.
* Prints errors or warnings to console if something is wrong.
* Prints errors or warnings to console if something is wrong.
* @return Whether Skript can continue loading at all.
* @return Whether Skript can continue loading at all.
*/
*/
private static boolean checkServerPlatform() {
private static boolean checkServerPlatform() {
String bukkitV = Bukkit.getBukkitVersion();
String bukkitV = Bukkit.getBukkitVersion();
Matcher m = Pattern.compile("\\d+\\.\\d+(\\.\\d+)?").matcher(bukkitV);
Matcher m = Pattern.compile("\\d+\\.\\d+(\\.\\d+)?").matcher(bukkitV);
if (!m.find()) {
if (!m.find()) {
Skript.error("The Bukkit version '" + bukkitV + "' does not contain a version number which is required for Skript to enable or disable certain features. " +
Skript.error("The Bukkit version '" + bukkitV + "' does not contain a version number which is required for Skript to enable or disable certain features. " +
"Skript will still work, but you might get random errors if you use features that are not available in your version of Bukkit.");
"Skript will still work, but you might get random errors if you use features that are not available in your version of Bukkit.");
minecraftVersion = new Version(666, 0, 0);
minecraftVersion = new Version(666, 0, 0);
} else {
} else {
minecraftVersion = new Version("" + m.group());
minecraftVersion = new Version("" + m.group());
}
}
Skript.debug("Loading for Minecraft " + minecraftVersion);
Skript.debug("Loading for Minecraft " + minecraftVersion);
// Check that MC version is supported
// Check that MC version is supported
if (!isRunningMinecraft(1, 9)) {
if (!isRunningMinecraft(1, 9)) {
if (isRunningMinecraft(1, 8)) { // 1.8 probably works, but let's spit a warning
if (isRunningMinecraft(1, 8)) { // 1.8 probably works, but let's spit a warning
Skript.warning("Using this version of Skript on 1.8 is highly discouraged.");
Skript.warning("Using this version of Skript on 1.8 is highly discouraged.");
Skript.warning("Some features have been disabled; use older Skript to restore them.");
Skript.warning("Some features have been disabled; use older Skript to restore them.");
Skript.warning("Also, there are probably bugs. And since 1.8 is not supported, they will not be fixed");
Skript.warning("Also, there are probably bugs. And since 1.8 is not supported, they will not be fixed");
} else { // Older versions definitely do not work
} else { // Older versions definitely do not work
Skript.error("This version of Skript does not work with Minecraft " + minecraftVersion);
Skript.error("This version of Skript does not work with Minecraft " + minecraftVersion);
Skript.error("You probably want Skript 2.2 or 2.1 (Google to find where to get them)");
Skript.error("You probably want Skript 2.2 or 2.1 (Google to find where to get them)");
Skript.error("Note that those versions are, of course, completely unsupported!");
Skript.error("Note that those versions are, of course, completely unsupported!");
return false;
return false;
}
}
}
}
// Check that current server platform is somewhat supported
// Check that current server platform is somewhat supported
serverPlatform = getServerPlatform();
serverPlatform = getServerPlatform();
Skript.debug("Server platform: " + serverPlatform);
Skript.debug("Server platform: " + serverPlatform);
if (!serverPlatform.works) {
if (!serverPlatform.works) {
Skript.error("It seems that this server platform (" + serverPlatform.name + ") does not work with Skript.");
Skript.error("It seems that this server platform (" + serverPlatform.name + ") does not work with Skript.");
if (SkriptConfig.allowUnsafePlatforms.value()) {
if (SkriptConfig.allowUnsafePlatforms.value()) {
Skript.error("However, you have chosen to ignore this. Skript will probably still not work.");
Skript.error("However, you have chosen to ignore this. Skript will probably still not work.");
} else {
} else {
Skript.error("To prevent potentially unsafe behaviour, Skript has been disabled.");
Skript.error("To prevent potentially unsafe behaviour, Skript has been disabled.");
Skript.error("You may re-enable it by adding a configuration option 'allow unsafe platforms: true'");
Skript.error("You may re-enable it by adding a configuration option 'allow unsafe platforms: true'");
Skript.error("Note that it is unlikely that Skript works correctly even if you do so.");
Skript.error("Note that it is unlikely that Skript works correctly even if you do so.");
Skript.error("A better idea would be to install Paper or Spigot in place of your current server.");
Skript.error("A better idea would be to install Paper or Spigot in place of your current server.");
return false;
return false;
}
}
} else if (!serverPlatform.supported) {
} else if (!serverPlatform.supported) {
Skript.warning("This server platform (" + serverPlatform.name + ") is not supported by Skript.");
Skript.warning("This server platform (" + serverPlatform.name + ") is not supported by Skript.");
Skript.warning("It will still probably work, but if it does not, you are on your own.");
Skript.warning("It will still probably work, but if it does not, you are on your own.");
Skript.warning("Skript officially supports Paper and Spigot.");
Skript.warning("Skript officially supports Paper and Spigot.");
}
}
// If nothing got triggered, everything is probably ok
// If nothing got triggered, everything is probably ok
return true;
return true;
}
}
@Override
@Override
public void onEnable() {
public void onEnable() {
if (disabled) {
if (disabled) {
Skript.error(m_invalid_reload.toString());
Skript.error(m_invalid_reload.toString());
setEnabled(false);
setEnabled(false);
return;
return;
}
}
handleJvmArguments(); // JVM arguments
handleJvmArguments(); // JVM arguments
version = new Version("" + getDescription().getVersion()); // Skript version
version = new Version("" + getDescription().getVersion()); // Skript version
Language.loadDefault(getAddonInstance());
Language.loadDefault(getAddonInstance());
Workarounds.init();
Workarounds.init();
// Start the updater
// Start the updater
// Note: if config prohibits update checks, it will NOT do network connections
// Note: if config prohibits update checks, it will NOT do network connections
try {
try {
this.updater = new SkriptUpdater();
this.updater = new SkriptUpdater();
} catch (Exception e) {
} catch (Exception e) {
Skript.exception(e, "Update checker could not be initialized.");
Skript.exception(e, "Update checker could not be initialized.");
}
}
if (!getDataFolder().isDirectory())
if (!getDataFolder().isDirectory())
getDataFolder().mkdirs();
getDataFolder().mkdirs();
final File scripts = new File(getDataFolder(), SCRIPTSFOLDER);
final File scripts = new File(getDataFolder(), SCRIPTSFOLDER);
final File config = new File(getDataFolder(), "config.sk");
final File config = new File(getDataFolder(), "config.sk");
final File features = new File(getDataFolder(), "features.sk");
final File features = new File(getDataFolder(), "features.sk");
if (!scripts.isDirectory() || !config.exists() || !features.exists()) {
if (!scripts.isDirectory() || !config.exists() || !features.exists()) {
ZipFile f = null;
ZipFile f = null;
try {
try {
boolean populateExamples = false;
boolean populateExamples = false;
if (!scripts.isDirectory()) {
if (!scripts.isDirectory()) {
if (!scripts.mkdirs())
if (!scripts.mkdirs())
throw new IOException("Could not create the directory " + scripts);
throw new IOException("Could not create the directory " + scripts);
populateExamples = true;
populateExamples = true;
}
}
f = new ZipFile(getFile());
f = new ZipFile(getFile());
for (final ZipEntry e : new EnumerationIterable<ZipEntry>(f.entries())) {
for (final ZipEntry e : new EnumerationIterable<ZipEntry>(f.entries())) {
if (e.isDirectory())
if (e.isDirectory())
continue;
continue;
File saveTo = null;
File saveTo = null;
if (e.getName().startsWith(SCRIPTSFOLDER + "/") && populateExamples) {
if (e.getName().startsWith(SCRIPTSFOLDER + "/") && populateExamples) {
final String fileName = e.getName().substring(e.getName().lastIndexOf('/') + 1);
final String fileName = e.getName().substring(e.getName().lastIndexOf('/') + 1);
saveTo = new File(scripts, (fileName.startsWith("-") ? "" : "-") + fileName);
saveTo = new File(scripts, (fileName.startsWith("-") ? "" : "-") + fileName);
} else if (e.getName().equals("config.sk")) {
} else if (e.getName().equals("config.sk")) {
if (!config.exists())
if (!config.exists())
saveTo = config;
saveTo = config;
// } else if (e.getName().startsWith("aliases-") && e.getName().endsWith(".sk") && !e.getName().contains("/")) {
// } else if (e.getName().startsWith("aliases-") && e.getName().endsWith(".sk") && !e.getName().contains("/")) {
// final File af = new File(getDataFolder(), e.getName());
// final File af = new File(getDataFolder(), e.getName());
// if (!af.exists())
// if (!af.exists())
// saveTo = af;
// saveTo = af;
} else if (e.getName().startsWith("features.sk")) {
} else if (e.getName().startsWith("features.sk")) {
if (!features.exists())
if (!features.exists())
saveTo = features;
saveTo = features;
}
}
if (saveTo != null) {
if (saveTo != null) {
final InputStream in = f.getInputStream(e);
final InputStream in = f.getInputStream(e);
try {
try {
assert in != null;
assert in != null;
FileUtils.save(in, saveTo);
FileUtils.save(in, saveTo);
} finally {
} finally {
in.close();
in.close();
}
}
}
}
}
}
info("Successfully generated the config and the example scripts.");
info("Successfully generated the config and the example scripts.");
} catch (final ZipException e) {} catch (final IOException e) {
} catch (final ZipException e) {} catch (final IOException e) {
error("Error generating the default files: " + ExceptionUtils.toString(e));
error("Error generating the default files: " + ExceptionUtils.toString(e));
} finally {
} finally {
if (f != null) {
if (f != null) {
try {
try {
f.close();
f.close();
} catch (final IOException e) {}
} catch (final IOException e) {}
}
}
}
}
}
}
// Load classes which are always safe to use
// Load classes which are always safe to use
new JavaClasses(); // These may be needed in configuration
new JavaClasses(); // These may be needed in configuration
// And then not-so-safe classes
// And then not-so-safe classes
Throwable classLoadError = null;
Throwable classLoadError = null;
try {
try {
new SkriptClasses();
new SkriptClasses();
} catch (Throwable e) {
} catch (Throwable e) {
classLoadError = e;
classLoadError = e;
}
}
// Config must be loaded after Java and Skript classes are parseable
// Config must be loaded after Java and Skript classes are parseable
// ... but also before platform check, because there is a config option to ignore some errors
// ... but also before platform check, because there is a config option to ignore some errors
SkriptConfig.load();
SkriptConfig.load();
// Use the updater, now that it has been configured to (not) do stuff
// Use the updater, now that it has been configured to (not) do stuff
if (updater != null) {
if (updater != null) {
CommandSender console = Bukkit.getConsoleSender();
CommandSender console = Bukkit.getConsoleSender();
assert console != null;
assert console != null;
assert updater != null;
assert updater != null;
updater.updateCheck(console);
updater.updateCheck(console);
}
}
// Check server software, Minecraft version, etc.
// Check server software, Minecraft version, etc.
if (!checkServerPlatform()) {
if (!checkServerPlatform()) {
disabled = true; // Nothing was loaded, nothing needs to be unloaded
disabled = true; // Nothing was loaded, nothing needs to be unloaded
setEnabled(false); // Cannot continue; user got errors in console to tell what happened
setEnabled(false); // Cannot continue; user got errors in console to tell what happened
return;
return;
}
}
BukkitUnsafe.initialize(); // Needed for aliases
BukkitUnsafe.initialize(); // Needed for aliases
Aliases.load(); // Loaded before anything that might use them
Aliases.load(); // Loaded before anything that might use them
// If loading can continue (platform ok), check for potentially thrown error
// If loading can continue (platform ok), check for potentially thrown error
if (classLoadError != null) {
if (classLoadError != null) {
exception(classLoadError);
exception(classLoadError);
setEnabled(false);
setEnabled(false);
return;
return;
}
}
PluginCommand skriptCommand = getCommand("skript");
PluginCommand skriptCommand = getCommand("skript");
assert skriptCommand != null; // It is defined, unless build is corrupted or something like that
assert skriptCommand != null; // It is defined, unless build is corrupted or something like that
skriptCommand.setExecutor(new SkriptCommand());
skriptCommand.setExecutor(new SkriptCommand());
// Load Bukkit stuff. It is done after platform check, because something might be missing!
// Load Bukkit stuff. It is done after platform check, because something might be missing!
new BukkitClasses();
new BukkitClasses();
new BukkitEventValues();
new BukkitEventValues();
new DefaultComparators();
new DefaultComparators();
new DefaultConverters();
new DefaultConverters();
new DefaultFunctions();
new DefaultFunctions();
ChatMessages.registerListeners();
ChatMessages.registerListeners();
try {
try {
getAddonInstance().loadClasses("ch.njol.skript", "conditions", "effects", "events", "expressions", "entity");
getAddonInstance().loadClasses("ch.njol.skript", "conditions", "effects", "events", "expressions", "entity");
} catch (final Exception e) {
} catch (final Exception e) {
exception(e, "Could not load required .class files: " + e.getLocalizedMessage());
exception(e, "Could not load required .class files: " + e.getLocalizedMessage());
setEnabled(false);
setEnabled(false);
return;
return;
}
}
Language.setUseLocal(true);
Language.setUseLocal(true);
Commands.registerListeners();
Commands.registerListeners();
if (logNormal())
if (logNormal())
info(" " + Language.get("skript.copyright"));
info(" " + Language.get("skript.copyright"));
final long tick = testing() ? Bukkit.getWorlds().get(0).getFullTime() : 0;
final long tick = testing() ? Bukkit.getWorlds().get(0).getFullTime() : 0;
Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
@SuppressWarnings("synthetic-access")
@SuppressWarnings("synthetic-access")
@Override
@Override
public void run() {
public void run() {
assert Bukkit.getWorlds().get(0).getFullTime() == tick;
assert Bukkit.getWorlds().get(0).getFullTime() == tick;
// Load hooks from Skript jar
// Load hooks from Skript jar
try {
try {
try (JarFile jar = new JarFile(getFile())) {
try (JarFile jar = new JarFile(getFile())) {
for (final JarEntry e : new EnumerationIterable<>(jar.entries())) {
for (final JarEntry e : new EnumerationIterable<>(jar.entries())) {
if (e.getName().startsWith("ch/njol/skript/hooks/") && e.getName().endsWith("Hook.class") && StringUtils.count("" + e.getName(), '/') <= 5) {
if (e.getName().startsWith("ch/njol/skript/hooks/") && e.getName().endsWith("Hook.class") && StringUtils.count("" + e.getName(), '/') <= 5) {
final String c = e.getName().replace('/', '.').substring(0, e.getName().length() - ".class".length());
final String c = e.getName().replace('/', '.').substring(0, e.getName().length() - ".class".length());
try {
try {
final Class<?> hook = Class.forName(c, true, getClassLoader());
final Class<?> hook = Class.forName(c, true, getClassLoader());
if (hook != null && Hook.class.isAssignableFrom(hook) && !hook.isInterface() && Hook.class != hook) {
if (hook != null && Hook.class.isAssignableFrom(hook) && !hook.isInterface() && Hook.class != hook) {
hook.getDeclaredConstructor().setAccessible(true);
hook.getDeclaredConstructor().setAccessible(true);
hook.getDeclaredConstructor().newInstance();
hook.getDeclaredConstructor().newInstance();
}
}
} catch (final ClassNotFoundException ex) {
} catch (final ClassNotFoundException ex) {
Skript.exception(ex, "Cannot load class " + c);
Skript.exception(ex, "Cannot load class " + c);
} catch (final ExceptionInInitializerError err) {
} catch (final ExceptionInInitializerError err) {
Skript.exception(err.getCause(), "Class " + c + " generated an exception while loading");
Skript.exception(err.getCause(), "Class " + c + " generated an exception while loading");
}
}
continue;
continue;
}
}
}
}
}
}
} catch (final Exception e) {
} catch (final Exception e) {
error("Error while loading plugin hooks" + (e.getLocalizedMessage() == null ? "" : ": " + e.getLocalizedMessage()));
error("Error while loading plugin hooks" + (e.getLocalizedMessage() == null ? "" : ": " + e.getLocalizedMessage()));
Skript.exception(e);
Skript.exception(e);
}
}
Language.setUseLocal(false);
Language.setUseLocal(false);
if (TestMode.ENABLED) {
if (TestMode.ENABLED) {
info("Preparing Skript for testing...");
info("Preparing Skript for testing...");
tainted = true;
tainted = true;
try {
try {
getAddonInstance().loadClasses("ch.njol.skript", "tests");
getAddonInstance().loadClasses("ch.njol.skript", "tests");
} catch (IOException e) {
} catch (IOException e) {
Skript.exception("Failed to load testing environment.");
Skript.exception("Failed to load testing environment.");
Bukkit.getServer().shutdown();
Bukkit.getServer().shutdown();
}
}
}
}
stopAcceptingRegistrations();
stopAcceptingRegistrations();
Documentation.generate(); // TODO move to test classes?
Documentation.generate(); // TODO move to test classes?
if (logNormal())
if (logNormal())
info("Loading variables...");
info("Loading variables...");
final long vls = System.currentTimeMillis();
final long vls = System.currentTimeMillis();
final LogHandler h = SkriptLogger.startLogHandler(new ErrorDescLogHandler() {
final LogHandler h = SkriptLogger.startLogHandler(new ErrorDescLogHandler() {
// private final List<LogEntry> log = new ArrayList<LogEntry>();
// private final List<LogEntry> log = new ArrayList<LogEntry>();
@Override
@Override
public LogResult log(final LogEntry entry) {
public LogResult log(final LogEntry entry) {
super.log(entry);
super.log(entry);
if (entry.level.intValue() >= Level.SEVERE.intValue()) {
if (entry.level.intValue() >= Level.SEVERE.intValue()) {
logEx(entry.message); // no [Skript] prefix
logEx(entry.message); // no [Skript] prefix
return LogResult.DO_NOT_LOG;
return LogResult.DO_NOT_LOG;
} else {
} else {
// log.add(entry);
// log.add(entry);
// return LogResult.CACHED;
// return LogResult.CACHED;
return LogResult.LOG;
return LogResult.LOG;
}
}
}
}
@Override
@Override
protected void beforeErrors() {
protected void beforeErrors() {
logEx();
logEx();
logEx("===!!!=== Skript variable load error ===!!!===");
logEx("===!!!=== Skript variable load error ===!!!===");
logEx("Unable to load (all) variables:");
logEx("Unable to load (all) variables:");
}
}
@Override
@Override
protected void afterErrors() {
protected void afterErrors() {
logEx();
logEx();
logEx("Skript will work properly, but old variables might not be available at all and new ones may or may not be saved until Skript is able to create a backup of the old file and/or is able to connect to the database (which requires a restart of Skript)!");
logEx("Skript will work properly, but old variables might not be available at all and new ones may or may not be saved until Skript is able to create a backup of the old file and/or is able to connect to the database (which requires a restart of Skript)!");
logEx();
logEx();
}
}
@Override
@Override
protected void onStop() {
protected void onStop() {
super.onStop();
super.onStop();
// SkriptLogger.logAll(log);
// SkriptLogger.logAll(log);
}
}
});
});
final CountingLogHandler c = SkriptLogger.startLogHandler(new CountingLogHandler(SkriptLogger.SEVERE));
final CountingLogHandler c = SkriptLogger.startLogHandler(new CountingLogHandler(SkriptLogger.SEVERE));
try {
try {
if (!Variables.load())
if (!Variables.load())
if (c.getCount() == 0)
if (c.getCount() == 0)
error("(no information available)");
error("(no information available)");
} finally {
} finally {
c.stop();
c.stop();
h.stop();
h.stop();
}
}
// Skript initialization done
// Skript initialization done
debug("Early init done");
debug("Early init done");
if (TestMode.ENABLED) { // Ignore late init (scripts, etc.) in test mode
if (TestMode.ENABLED) { // Ignore late init (scripts, etc.) in test mode
if (TestMode.DEV_MODE) { // Run tests NOW!
if (TestMode.DEV_MODE) { // Run tests NOW!
info("Test development mode enabled. Test scripts are at " + TestMode.TEST_DIR);
info("Test development mode enabled. Test scripts are at " + TestMode.TEST_DIR);
} else {
} else {
info("Running all tests from " + TestMode.TEST_DIR);
info("Running all tests from " + TestMode.TEST_DIR);
// Treat parse errors as fatal testing failure
// Treat parse errors as fatal testing failure
@SuppressWarnings("null")
@SuppressWarnings("null")
CountingLogHandler errorCounter = new CountingLogHandler(Level.SEVERE);
CountingLogHandler errorCounter = new CountingLogHandler(Level.SEVERE);
try {
try {
SkriptLogger.startLogHandler(errorCounter);
SkriptLogger.startLogHandler(errorCounter);
File testDir = TestMode.TEST_DIR.toFile();
File testDir = TestMode.TEST_DIR.toFile();
assert testDir != null;
assert testDir != null;
ScriptLoader.loadScripts(ScriptLoader.loadStructures(testDir));
ScriptLoader.loadScripts(ScriptLoader.loadStructures(testDir));
} finally {
} finally {
errorCounter.stop();
errorCounter.stop();
}
}
Bukkit.getPluginManager().callEvent(new SkriptTestEvent());
Bukkit.getPluginManager().callEvent(new SkriptTestEvent());
info("Collecting results to " + TestMode.RESULTS_FILE);
info("Collecting results to " + TestMode.RESULTS_FILE);
if (errorCounter.getCount() > 0) {
if (errorCounter.getCount() > 0) {
TestTracker.testStarted("parse scripts");
TestTracker.testStarted("parse scripts");
TestTracker.testFailed(errorCounter.getCount() + " error(s) found");
TestTracker.testFailed(errorCounter.getCount() + " error(s) found");
}
}
if (errored) { // Check for exceptions thrown while script was executing
if (errored) { // Check for exceptions thrown while script was executing
TestTracker.testStarted("run scripts");
TestTracker.testStarted("run scripts");
TestTracker.testFailed("exception was thrown during execution");
TestTracker.testFailed("exception was thrown during execution");
}
}
String results = new Gson().toJson(TestTracker.collectResults());
String results = new Gson().toJson(TestTracker.collectResults());
try {
try {
Files.write(TestMode.RESULTS_FILE, results.getBytes(StandardCharsets.UTF_8));
Files.write(TestMode.RESULTS_FILE, results.getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
} catch (IOException e) {
Skript.exception(e, "Failed to write test results.");
Skript.exception(e, "Failed to write test results.");
}
}
info("Testing done, shutting down the server.");
info("Testing done, shutting down the server.");
Bukkit.getServer().shutdown();
Bukkit.getServer().shutdown();
}
}
return;
return;
}
}
final long vld = System.currentTimeMillis() - vls;
final long vld = System.currentTimeMillis() - vls;
if (logNormal())
if (logNormal())
info("Loaded " + Variables.numVariables() + " variables in " + ((vld / 100) / 10.) + " seconds");
info("Loaded " + Variables.numVariables() + " variables in " + ((vld / 100) / 10.) + " seconds");
ScriptLoader.loadScripts();
ScriptLoader.loadScripts();
Skript.info(m_finished_loading.toString());
Skript.info(m_finished_loading.toString());
EvtSkript.onSkriptStart();
EvtSkript.onSkriptStart();
final Metrics metrics = new Metrics(Skript.this);
final Metrics metrics = new Metrics(Skript.this);
metrics.addCustomChart(new Metrics.SimplePie("pluginLanguage") {
metrics.addCustomChart(new Metrics.SimplePie("pluginLanguage") {
@Override
@Override
public String getValue() {
public String getValue() {
return Language.getName();
return Language.getName();
}
}
});
});
metrics.addCustomChart(new Metrics.SimplePie("effectCommands") {
metrics.addCustomChart(new Metrics.SimplePie("effectCommands") {
@Override
@Override
public String getValue() {
public String getValue() {
return "" + SkriptConfig.enableEffectCommands.value();
return "" + SkriptConfig.enableEffectCommands.value();
}
}
});
});
metrics.addCustomChart(new Metrics.SimplePie("uuidsWithPlayers") {
metrics.addCustomChart(new Metrics.SimplePie("uuidsWithPlayers") {
@Override
@Override
public String getValue() {
public String getValue() {
return "" + SkriptConfig.usePlayerUUIDsInVariableNames.value();
return "" + SkriptConfig.usePlayerUUIDsInVariableNames.value();
}
}
});
});
metrics.addCustomChart(new Metrics.SimplePie("playerVariableFix") {
metrics.addCustomChart(new Metrics.SimplePie("playerVariableFix") {
@Override
@Override
public String getValue() {
public String getValue() {
return "" + SkriptConfig.enablePlayerVariableFix.value();
return "" + SkriptConfig.enablePlayerVariableFix.value();
}
}
});
});
metrics.addCustomChart(new Metrics.SimplePie("logVerbosity") {
metrics.addCustomChart(new Metrics.SimplePie("logVerbosity") {
@Override
@Override
public String getValue() {
public String getValue() {
return "" + SkriptConfig.verbosity.value().name().toLowerCase(Locale.ENGLISH).replace('_', ' ');
return "" + SkriptConfig.verbosity.value().name().toLowerCase(Locale.ENGLISH).replace('_', ' ');
}
}
});
});
metrics.addCustomChart(new Metrics.SimplePie("pluginPriority") {
metrics.addCustomChart(new Metrics.SimplePie("pluginPriority") {
@Override
@Override
public String getValue() {
public String getValue() {
return "" + SkriptConfig.defaultEventPriority.value().name().toLowerCase(Locale.ENGLISH).replace('_', ' ');
return "" + SkriptConfig.defaultEventPriority.value().name().toLowerCase(Locale.ENGLISH).replace('_', ' ');
}
}
});
});
metrics.addCustomChart(new Metrics.SimplePie("logPlayerCommands") {
metrics.addCustomChart(new Metrics.SimplePie("logPlayerCommands") {
@Override
@Override
public String getValue() {
public String getValue() {
return "" + SkriptConfig.logPlayerCommands.value();
return "" + SkriptConfig.logPlayerCommands.value();
}
}
});
});
metrics.addCustomChart(new Metrics.SimplePie("maxTargetDistance") {
metrics.addCustomChart(new Metrics.SimplePie("maxTargetDistance") {
@Override
@Override
public String getValue() {
public String getValue() {
return "" + SkriptConfig.maxTargetBlockDistance.value();
return "" + SkriptConfig.maxTargetBlockDistance.value();
}
}
});
});
metrics.addCustomChart(new Metrics.SimplePie("softApiExceptions") {
metrics.addCustomChart(new Metrics.SimplePie("softApiExceptions") {
@Override
@Override
public String getValue() {
public String getValue() {
return "" + SkriptConfig.apiSoftExceptions.value();
return "" + SkriptConfig.apiSoftExceptions.value();
}
}
});
});
metrics.addCustomChart(new Metrics.SimplePie("timingsStatus") {
metrics.addCustomChart(new Metrics.SimplePie("timingsStatus") {
@Override
@Override
public String getValue() {
public String getValue() {
if (!Skript.classExists("co.aikar.timings.Timings"))
if (!Skript.classExists("co.aikar.timings.Timings"))
return "unsupported";
return "unsupported";
else
else
return "" + SkriptConfig.enableTimings.value();
return "" + SkriptConfig.enableTimings.value();
}
}
});
});
metrics.addCustomChart(new Metrics.SimplePie("parseLinks") {
metrics.addCustomChart(new Metrics.SimplePie("parseLinks") {
@Override
@Override
public String getValue() {
public String getValue() {
return "" + ChatMessages.linkParseMode.name().toLowerCase(Locale.ENGLISH);
return "" + ChatMessages.linkParseMode.name().toLo
}
});
metrics.addCustomChart(new Metrics.Simple