Merge pull request #17 from cyberpwnn/master

Fixes
This commit is contained in:
Dan 2020-10-22 11:09:24 -04:00 committed by GitHub
commit 90ed2f084d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 650 additions and 75 deletions

24
pom.xml
View File

@ -1,4 +1,5 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -152,10 +153,6 @@
<id>bcn</id> <id>bcn</id>
<url>http://bytecode.ninja/repository/bcn/</url> <url>http://bytecode.ninja/repository/bcn/</url>
</repository> </repository>
<repository>
<id>CodeMC</id>
<url>https://repo.codemc.org/repository/maven-public</url>
</repository>
<repository> <repository>
<id>nexus</id> <id>nexus</id>
<name>Lumine Releases</name> <name>Lumine Releases</name>
@ -192,18 +189,6 @@
<version>1.16.2</version> <version>1.16.2</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.bukkit.craftbukkit</groupId>
<artifactId>cb-1.15.1</artifactId>
<version>1.15.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit.craftbukkit</groupId>
<artifactId>cb-1.14.4</artifactId>
<version>1.14.4</version>
<scope>provided</scope>
</dependency>
<!-- Hooks --> <!-- Hooks -->
<dependency> <dependency>
<groupId>com.sk89q.worldedit</groupId> <groupId>com.sk89q.worldedit</groupId>
@ -230,11 +215,6 @@
<artifactId>caffeine</artifactId> <artifactId>caffeine</artifactId>
<version>2.8.5</version> <version>2.8.5</version>
</dependency> </dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>1.7</version>
</dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>

View File

@ -7,7 +7,6 @@ import java.io.IOException;
import java.net.URL; import java.net.URL;
import com.volmit.iris.link.CitizensLink; import com.volmit.iris.link.CitizensLink;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.World.Environment; import org.bukkit.World.Environment;
@ -43,6 +42,7 @@ import com.volmit.iris.util.IrisLock;
import com.volmit.iris.util.J; import com.volmit.iris.util.J;
import com.volmit.iris.util.KList; import com.volmit.iris.util.KList;
import com.volmit.iris.util.M; import com.volmit.iris.util.M;
import com.volmit.iris.util.MetricsLite;
import com.volmit.iris.util.MortarPlugin; import com.volmit.iris.util.MortarPlugin;
import com.volmit.iris.util.NastyRunnable; import com.volmit.iris.util.NastyRunnable;
import com.volmit.iris.util.Permission; import com.volmit.iris.util.Permission;
@ -208,7 +208,10 @@ public class Iris extends MortarPlugin
private void bstats() private void bstats()
{ {
new Metrics(this, 8757); J.s(() ->
{
new MetricsLite(Iris.instance, 8757);
});
} }
public static File getTemp() public static File getTemp()

View File

@ -30,6 +30,14 @@ public class IrisSettings
@Desc("Iris uses a lot of caching to speed up chunk generation. Setting this higher uses more memory, but may improve performance. Anything past 8,000 should be avoided because there is little benefit past this value.") @Desc("Iris uses a lot of caching to speed up chunk generation. Setting this higher uses more memory, but may improve performance. Anything past 8,000 should be avoided because there is little benefit past this value.")
public int atomicCacheSize = 3000; public int atomicCacheSize = 3000;
@DontObfuscate
@Desc("Max pregen async chunk threads.")
public int maxAsyncChunkPregenThreads = 300;
@DontObfuscate
@Desc("More cpu for pregen gui but looks nice.")
public boolean maxPregenGuiFPS = false;
@DontObfuscate @DontObfuscate
@Desc("Compress parallax data in memory to reduce memory usage in exchange for more cpu usage.") @Desc("Compress parallax data in memory to reduce memory usage in exchange for more cpu usage.")
public boolean parallaxCompression = true; public boolean parallaxCompression = true;
@ -50,6 +58,10 @@ public class IrisSettings
@Desc("System Effects") @Desc("System Effects")
public boolean systemEffects = true; public boolean systemEffects = true;
@DontObfuscate
@Desc("Disable all nms")
public boolean disableNMS = false;
@DontObfuscate @DontObfuscate
@Desc("System Spawn Overrides") @Desc("System Spawn Overrides")
public boolean systemEntitySpawnOverrides = true; public boolean systemEntitySpawnOverrides = true;

View File

@ -46,6 +46,9 @@ public class CommandIris extends MortarCommand
@Command @Command
private CommandIrisPregen pregen; private CommandIrisPregen pregen;
@Command
private CommandIrisReload reload;
public CommandIris() public CommandIris()
{ {
super("iris", "ir", "irs"); super("iris", "ir", "irs");

View File

@ -40,36 +40,30 @@ public class CommandIrisPregen extends MortarCommand
} }
return true; return true;
} }
/* TODO: help
else if(args[0].equalsIgnoreCase("pause")) else if(args[0].equalsIgnoreCase("pause"))
{ {
if(PregenJob.task == -1) if(PregenJob.task == -1)
{ {
sender.sendMessage("No Active Pregens"); sender.sendMessage("No Active Pregens");
} }
else else
{ {
if (PregenJob.isPaused()) { PregenJob.pauseResume();
PregenJob.resume();
} else { if(PregenJob.isPaused())
PregenJob.pause();
}
sender.sendMessage("Paused Active Pregen");
}
return true;
} else if(args[0].equalsIgnoreCase("resume")){
if(!PregenJob.isPaused())
{ {
sender.sendMessage("No Paused Pregens"); sender.sendMessage("Pregen Paused");
} }
else else
{ {
sender.sendMessage("Resumed Paused Pregen"); sender.sendMessage("Pregen Resumed");
PregenJob.resume();
} }
}
return true; return true;
} }
*/
if(sender.isPlayer()) if(sender.isPlayer())
{ {

View File

@ -3,6 +3,7 @@ package com.volmit.iris.gen.nms;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.IrisSettings;
import com.volmit.iris.gen.nms.v16_2.NMSBinding16_2; import com.volmit.iris.gen.nms.v16_2.NMSBinding16_2;
import com.volmit.iris.gen.nms.v1X.NMSBinding1X; import com.volmit.iris.gen.nms.v1X.NMSBinding1X;
import com.volmit.iris.util.KMap; import com.volmit.iris.util.KMap;
@ -22,6 +23,11 @@ public class INMS
private static final String getNMSTag() private static final String getNMSTag()
{ {
if(IrisSettings.get().disableNMS)
{
return "BUKKIT";
}
try try
{ {
return Bukkit.getServer().getClass().getCanonicalName().split("\\Q.\\E")[3]; return Bukkit.getServer().getClass().getCanonicalName().split("\\Q.\\E")[3];

View File

@ -2,6 +2,8 @@ package com.volmit.iris.gen.nms.v16_2;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@ -210,11 +212,85 @@ class NMSCreator16_2 implements INMSCreator
private Dimension getConsoleDimension(DedicatedServer console) private Dimension getConsoleDimension(DedicatedServer console)
{ {
if(PaperLib.isPaper()) Dimension dim = null;
try
{ {
return new V((MinecraftServer) console, true).get("customRegistry"); dim = new V((MinecraftServer) console, true).get("customRegistry");
if(dim != null)
{
return dim;
}
} }
return console.f; catch(Throwable e)
{
}
try
{
dim = new V((MinecraftServer) console, true).get("f");
if(dim != null)
{
return dim;
}
}
catch(Throwable e)
{
}
for(Field i : MinecraftServer.class.getDeclaredFields())
{
if(i.getType().equals(dim.getClass()))
{
i.setAccessible(true);
if(Modifier.isStatic(i.getModifiers()))
{
try
{
return (Dimension) i.get(null);
}
catch(Throwable e)
{
e.printStackTrace();
}
}
else
{
try
{
return (Dimension) i.get((MinecraftServer) console);
}
catch(Throwable e)
{
e.printStackTrace();
}
}
}
}
if(dim == null)
{
try
{
throw new RuntimeException("Cannot find dimension field!");
}
catch(Throwable e)
{
e.printStackTrace();
}
}
return dim;
} }
} }

View File

@ -5,6 +5,8 @@ import java.awt.Font;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Image; import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver; import java.awt.image.ImageObserver;
import java.io.File; import java.io.File;
@ -16,13 +18,14 @@ import javax.swing.JFrame;
import javax.swing.JPanel; import javax.swing.JPanel;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.IrisSettings;
import com.volmit.iris.util.ChunkPosition; import com.volmit.iris.util.ChunkPosition;
import com.volmit.iris.util.J; import com.volmit.iris.util.J;
import com.volmit.iris.util.KList; import com.volmit.iris.util.KList;
import com.volmit.iris.util.M; import com.volmit.iris.util.M;
import com.volmit.iris.util.PregenJob; import com.volmit.iris.util.PregenJob;
public class PregenGui extends JPanel public class PregenGui extends JPanel implements KeyListener
{ {
private PregenJob job; private PregenJob job;
private static final long serialVersionUID = 2094606939770332040L; private static final long serialVersionUID = 2094606939770332040L;
@ -76,12 +79,25 @@ public class PregenGui extends JPanel
String[] prog = job.getProgress(); String[] prog = job.getProgress();
int h = g.getFontMetrics().getHeight() + 5; int h = g.getFontMetrics().getHeight() + 5;
int hh = 20; int hh = 20;
if(job.paused())
{
g.drawString("PAUSED", 20, hh += h);
g.drawString("Press P to Resume", 20, hh += h);
}
else
{
for(String i : prog) for(String i : prog)
{ {
g.drawString(i, 20, hh += h); g.drawString(i, 20, hh += h);
} }
J.sleep((long) 250); g.drawString("Press P to Pause", 20, hh += h);
}
J.sleep((long) (IrisSettings.get().isMaxPregenGuiFPS() ? 4 : 250));
repaint(); repaint();
} }
@ -104,6 +120,7 @@ public class PregenGui extends JPanel
{ {
JFrame frame = new JFrame("Pregen View"); JFrame frame = new JFrame("Pregen View");
PregenGui nv = new PregenGui(); PregenGui nv = new PregenGui();
frame.addKeyListener(nv);
nv.l = new ReentrantLock(); nv.l = new ReentrantLock();
nv.job = j; nv.job = j;
j.subscribe((c, b) -> j.subscribe((c, b) ->
@ -142,4 +159,25 @@ public class PregenGui extends JPanel
createAndShowGUI(g); createAndShowGUI(g);
}); });
} }
@Override
public void keyTyped(KeyEvent e)
{
}
@Override
public void keyPressed(KeyEvent e)
{
}
@Override
public void keyReleased(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_P)
{
PregenJob.pauseResume();
}
}
} }

View File

@ -0,0 +1,434 @@
package com.volmit.iris.util;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicePriority;
import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;
/**
* bStats collects some data for plugin authors.
* <p>
* Check out https://bStats.org/ to learn more about bStats!
*/
public class MetricsLite
{
static
{
// You can use the property to disable the check in your test environment
if(System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false"))
{
// Maven's Relocate is clever and changes strings, too. So we have to use this
// little "trick" ... :D
final String defaultPackage = new String(new byte[] {'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'k', 'k', 'i', 't'});
final String examplePackage = new String(new byte[] {'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
// We want to make sure nobody just copy & pastes the example and use the wrong
// package names
if(MetricsLite.class.getPackage().getName().equals(defaultPackage) || MetricsLite.class.getPackage().getName().equals(examplePackage))
{
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
}
}
}
// The version of this bStats class
public static final int B_STATS_VERSION = 1;
// The url to which the data is sent
private static final String URL = "https://bStats.org/submitData/bukkit";
// Is bStats enabled on this server?
private boolean enabled;
// Should failed requests be logged?
private static boolean logFailedRequests;
// Should the sent data be logged?
private static boolean logSentData;
// Should the response text be logged?
private static boolean logResponseStatusText;
// The uuid of the server
private static String serverUUID;
// The plugin
private final Plugin plugin;
// The plugin id
private final int pluginId;
/**
* Class constructor.
*
* @param plugin
* The plugin which stats should be submitted.
* @param pluginId
* The id of the plugin. It can be found at
* <a href="https://bstats.org/what-is-my-plugin-id">What is my
* plugin id?</a>
*/
public MetricsLite(Plugin plugin, int pluginId)
{
if(plugin == null)
{
throw new IllegalArgumentException("Plugin cannot be null!");
}
this.plugin = plugin;
this.pluginId = pluginId;
// Get the config file
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
File configFile = new File(bStatsFolder, "config.yml");
YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
// Check if the config file exists
if(!config.isSet("serverUuid"))
{
// Add default values
config.addDefault("enabled", true);
// Every server gets it's unique random id.
config.addDefault("serverUuid", UUID.randomUUID().toString());
// Should failed request be logged?
config.addDefault("logFailedRequests", false);
// Should the sent data be logged?
config.addDefault("logSentData", false);
// Should the response text be logged?
config.addDefault("logResponseStatusText", false);
// Inform the server owners about bStats
config.options().header("bStats collects some data for plugin authors like how many servers are using their plugins.\n" + "To honor their work, you should not disable it.\n" + "This has nearly no effect on the server performance!\n" + "Check out https://bStats.org/ to learn more :)").copyDefaults(true);
try
{
config.save(configFile);
}
catch(IOException ignored)
{
}
}
// Load the data
serverUUID = config.getString("serverUuid");
logFailedRequests = config.getBoolean("logFailedRequests", false);
enabled = config.getBoolean("enabled", true);
logSentData = config.getBoolean("logSentData", false);
logResponseStatusText = config.getBoolean("logResponseStatusText", false);
if(enabled)
{
boolean found = false;
// Search for all other bStats Metrics classes to see if we are the first one
for(Class<?> service : Bukkit.getServicesManager().getKnownServices())
{
try
{
service.getField("B_STATS_VERSION"); // Our identifier :)
found = true; // We aren't the first
break;
}
catch(NoSuchFieldException ignored)
{
}
}
// Register our service
Bukkit.getServicesManager().register(MetricsLite.class, this, plugin, ServicePriority.Normal);
if(!found)
{
// We are the first!
startSubmitting();
}
}
}
/**
* Checks if bStats is enabled.
*
* @return Whether bStats is enabled or not.
*/
public boolean isEnabled()
{
return enabled;
}
/**
* Starts the Scheduler which submits our data every 30 minutes.
*/
private void startSubmitting()
{
final Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags
timer.scheduleAtFixedRate(new TimerTask()
{
@Override
public void run()
{
if(!plugin.isEnabled())
{ // Plugin was disabled
timer.cancel();
return;
}
// Nevertheless we want our code to run in the Bukkit main thread, so we have to
// use the Bukkit scheduler
// Don't be afraid! The connection to the bStats server is still async, only the
// stats collection is sync ;)
Bukkit.getScheduler().runTask(plugin, () -> submitData());
}
}, 1000 * 60 * 5, 1000 * 60 * 30);
// Submit the data every 30 minutes, first time after 5 minutes to give other
// plugins enough time to start
// WARNING: Changing the frequency has no effect but your plugin WILL be
// blocked/deleted!
// WARNING: Just don't do it!
}
/**
* Gets the plugin specific data. This method is called using Reflection.
*
* @return The plugin specific data.
*/
public JsonObject getPluginData()
{
JsonObject data = new JsonObject();
String pluginName = plugin.getDescription().getName();
String pluginVersion = plugin.getDescription().getVersion();
data.addProperty("pluginName", pluginName); // Append the name of the plugin
data.addProperty("id", pluginId); // Append the id of the plugin
data.addProperty("pluginVersion", pluginVersion); // Append the version of the plugin
data.add("customCharts", new JsonArray());
return data;
}
/**
* Gets the server specific data.
*
* @return The server specific data.
*/
private JsonObject getServerData()
{
// Minecraft specific data
int playerAmount;
try
{
// Around MC 1.8 the return type was changed to a collection from an array,
// This fixes java.lang.NoSuchMethodError:
// org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection;
Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
playerAmount = onlinePlayersMethod.getReturnType().equals(Collection.class) ? ((Collection<?>) onlinePlayersMethod.invoke(Bukkit.getServer())).size() : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length;
}
catch(Exception e)
{
playerAmount = Bukkit.getOnlinePlayers().size(); // Just use the new method if the Reflection failed
}
int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
String bukkitVersion = Bukkit.getVersion();
String bukkitName = Bukkit.getName();
// OS/Java specific data
String javaVersion = System.getProperty("java.version");
String osName = System.getProperty("os.name");
String osArch = System.getProperty("os.arch");
String osVersion = System.getProperty("os.version");
int coreCount = Runtime.getRuntime().availableProcessors();
JsonObject data = new JsonObject();
data.addProperty("serverUUID", serverUUID);
data.addProperty("playerAmount", playerAmount);
data.addProperty("onlineMode", onlineMode);
data.addProperty("bukkitVersion", bukkitVersion);
data.addProperty("bukkitName", bukkitName);
data.addProperty("javaVersion", javaVersion);
data.addProperty("osName", osName);
data.addProperty("osArch", osArch);
data.addProperty("osVersion", osVersion);
data.addProperty("coreCount", coreCount);
return data;
}
/**
* Collects the data and sends it afterwards.
*/
private void submitData()
{
final JsonObject data = getServerData();
JsonArray pluginData = new JsonArray();
// Search for all other bStats Metrics classes to get their plugin data
for(Class<?> service : Bukkit.getServicesManager().getKnownServices())
{
try
{
service.getField("B_STATS_VERSION"); // Our identifier :)
for(RegisteredServiceProvider<?> provider : Bukkit.getServicesManager().getRegistrations(service))
{
try
{
Object plugin = provider.getService().getMethod("getPluginData").invoke(provider.getProvider());
if(plugin instanceof JsonObject)
{
pluginData.add((JsonObject) plugin);
}
else
{ // old bstats version compatibility
try
{
Class<?> jsonObjectJsonSimple = Class.forName("org.json.simple.JSONObject");
if(plugin.getClass().isAssignableFrom(jsonObjectJsonSimple))
{
Method jsonStringGetter = jsonObjectJsonSimple.getDeclaredMethod("toJSONString");
jsonStringGetter.setAccessible(true);
String jsonString = (String) jsonStringGetter.invoke(plugin);
JsonObject object = new JsonParser().parse(jsonString).getAsJsonObject();
pluginData.add(object);
}
}
catch(ClassNotFoundException e)
{
// minecraft version 1.14+
if(logFailedRequests)
{
this.plugin.getLogger().log(Level.SEVERE, "Encountered unexpected exception ", e);
}
}
}
}
catch(NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored)
{
}
}
}
catch(NoSuchFieldException ignored)
{
}
}
data.add("plugins", pluginData);
// Create a new thread for the connection to the bStats server
new Thread(() ->
{
try
{
// Send the data
sendData(plugin, data);
}
catch(Exception e)
{
// Something went wrong! :(
if(logFailedRequests)
{
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
}
}
}).start();
}
/**
* Sends the data to the bStats server.
*
* @param plugin
* Any plugin. It's just used to get a logger instance.
* @param data
* The data to send.
* @throws Exception
* If the request failed.
*/
private static void sendData(Plugin plugin, JsonObject data) throws Exception
{
if(data == null)
{
throw new IllegalArgumentException("Data cannot be null!");
}
if(Bukkit.isPrimaryThread())
{
throw new IllegalAccessException("This method must not be called from the main thread!");
}
if(logSentData)
{
plugin.getLogger().info("Sending data to bStats: " + data);
}
HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
// Compress the data to save bandwidth
byte[] compressedData = compress(data.toString());
// Add headers
connection.setRequestMethod("POST");
connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close");
connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
// Send data
connection.setDoOutput(true);
try(DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()))
{
outputStream.write(compressedData);
}
StringBuilder builder = new StringBuilder();
try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream())))
{
String line;
while((line = bufferedReader.readLine()) != null)
{
builder.append(line);
}
}
if(logResponseStatusText)
{
plugin.getLogger().info("Sent data to bStats and received response: " + builder);
}
}
/**
* Gzips the given String.
*
* @param str
* The string to gzip.
* @return The gzipped String.
* @throws IOException
* If the compression failed.
*/
private static byte[] compress(final String str) throws IOException
{
if(str == null)
{
return null;
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try(GZIPOutputStream gzip = new GZIPOutputStream(outputStream))
{
gzip.write(str.getBytes(StandardCharsets.UTF_8));
}
return outputStream.toByteArray();
}
}

View File

@ -98,4 +98,9 @@ public class PrecisionStopwatch {
public boolean isProfiling() { public boolean isProfiling() {
return profiling; return profiling;
} }
public void rewind(long l)
{
startMillis -= l;
}
} }

View File

@ -12,15 +12,16 @@ import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkUnloadEvent; import org.bukkit.event.world.ChunkUnloadEvent;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.IrisSettings;
import com.volmit.iris.gen.IrisTerrainProvider; import com.volmit.iris.gen.IrisTerrainProvider;
import com.volmit.iris.gen.scaffold.IrisWorlds; import com.volmit.iris.gen.scaffold.IrisWorlds;
import com.volmit.iris.gui.PregenGui; import com.volmit.iris.gui.PregenGui;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import org.bukkit.scheduler.BukkitTask;
public class PregenJob implements Listener public class PregenJob implements Listener
{ {
private static PregenJob instance;
private World world; private World world;
private int size; private int size;
private int total; private int total;
@ -52,13 +53,15 @@ public class PregenJob implements Listener
private long nogen = M.ms(); private long nogen = M.ms();
private KList<ChunkPosition> requeueMCA = new KList<ChunkPosition>(); private KList<ChunkPosition> requeueMCA = new KList<ChunkPosition>();
private RollingSequence acps = new RollingSequence(PaperLib.isPaper() ? 8 : 32); private RollingSequence acps = new RollingSequence(PaperLib.isPaper() ? 8 : 32);
private BukkitTask pausedTask; private boolean paused = false;
private boolean isPaused = false; private long pausedAt = 0;
private double pms = 0;
int xc = 0; int xc = 0;
public PregenJob(World world, int size, MortarSender sender, Runnable onDone) public PregenJob(World world, int size, MortarSender sender, Runnable onDone)
{ {
g.set(0); g.set(0);
instance = this;
working = new Semaphore(tc()); working = new Semaphore(tc());
this.s = PrecisionStopwatch.start(); this.s = PrecisionStopwatch.start();
Iris.instance.registerListener(this); Iris.instance.registerListener(this);
@ -105,7 +108,7 @@ public class PregenJob implements Listener
public int tc() public int tc()
{ {
return 48; return IrisSettings.get().maxAsyncChunkPregenThreads;
} }
public static void stop() public static void stop()
@ -127,42 +130,36 @@ public class PregenJob implements Listener
task = -1; task = -1;
} }
// TODO: Cannot get paused value from this. Have to check bukkit tasks, not sure how.
// TODO: Trying to add functionality here to allow for pausing an continuing.
public static boolean isPaused(){
return false;
//return this.isPaused;
}
public static void pause() public static void pause()
{ {
try if(instance.paused)
{ {
// Save the task, tell bukkit to cancel it return;
stop();
} }
catch(Throwable e)
{
} instance.pms = instance.s.getMilliseconds();
task = -1; instance.paused = true;
instance.pausedAt = M.ms();
} }
public static void resume() public static void resume()
{ {
try if(!instance.paused)
{ {
// Load task and tell bukkit to continue it return;
} }
catch(Throwable e)
{
} instance.paused = false;
task = -1; instance.s.rewind(instance.pausedAt - M.ms());
} }
public void onTick() public void onTick()
{ {
if(paused)
{
return;
}
if(completed) if(completed)
{ {
return; return;
@ -192,7 +189,11 @@ public class PregenJob implements Listener
private void tickMetrics() private void tickMetrics()
{ {
long eta = (long) ((total - genned) * (s.getMilliseconds() / (double) genned)); long eta = (long) ((total - genned) * (s.getMilliseconds() / (double) genned));
String ss = "Pregen: " + Form.pc(Math.min((double) genned / (double) total, 1.0), 0) + ", Elapsed: " + Form.duration((long) s.getMilliseconds()) + ", ETA: " + (genned >= total - 5 ? "Any second..." : s.getMilliseconds() < 25000 ? "Calculating..." : Form.duration(eta)) + " MS: " + Form.duration((s.getMilliseconds() / (double) genned), 2); String ss = "Pregen: " + Form.pc(Math.min((double) genned / (double) total, 1.0), 0) + ", Elapsed: " +
Form.duration((long) (paused ? pms : s.getMilliseconds()))
+ ", ETA: " + (genned >= total - 5 ? "Any second..." : s.getMilliseconds() < 25000 ? "Calculating..." : Form.duration(eta)) + " MS: " + Form.duration((s.getMilliseconds() / (double) genned), 2);
Iris.info(ss); Iris.info(ss);
if(sender.isPlayer() && sender.player().isOnline()) if(sender.isPlayer() && sender.player().isOnline())
{ {
@ -459,7 +460,30 @@ public class PregenJob implements Listener
{ {
long eta = (long) ((total - genned) * 1000D / cps); long eta = (long) ((total - genned) * 1000D / cps);
return new String[] {"Progress: " + Form.pc(Math.min((double) genned / (double) total, 1.0), 0), "Generated: " + Form.f(genned) + " Chunks", "Remaining: " + Form.f(total - genned) + " Chunks", "Elapsed: " + Form.duration((long) s.getMilliseconds(), 2), "Estimate: " + ((genned >= total - 5 ? "Any second..." : s.getMilliseconds() < 25000 ? "Calculating..." : Form.duration(eta, 2))), "ChunksMS: " + Form.duration(1000D / cps, 2), "Chunks/s: " + Form.f(cps, 1), return new String[] {"Progress: " + Form.pc(Math.min((double) genned / (double) total, 1.0), 0), "Generated: " + Form.f(genned) + " Chunks", "Remaining: " + Form.f(total - genned) + " Chunks", "Elapsed: " + Form.duration((long) (paused ? pms : s.getMilliseconds()), 2), "Estimate: " + ((genned >= total - 5 ? "Any second..." : s.getMilliseconds() < 25000 ? "Calculating..." : Form.duration(eta, 2))), "ChunksMS: " + Form.duration(1000D / cps, 2), "Chunks/s: " + Form.f(cps, 1),
}; };
} }
public static void pauseResume()
{
if(instance.paused)
{
resume();
}
else
{
pause();
}
}
public static boolean isPaused()
{
return instance.paused;
}
public boolean paused()
{
return paused;
}
} }