// 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
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
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);