1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-19 19:25:48 +00:00

Merge branch 'master' into experimental

This commit is contained in:
TheBusyBiscuit 2020-07-24 16:36:08 +02:00 committed by GitHub
commit 499bbdbf70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 712 additions and 796 deletions

View File

@ -23,12 +23,15 @@
## Release Candidate 15 (TBD) ## Release Candidate 15 (TBD)
#### Additions #### Additions
* Added "Bone Block -> Bone meal" recipe to the Grind Stone
* Added a [Metrics module](https://github.com/Slimefun/MetricsModule) which allows us to release updates to metrics (bStats) independently from the main plugin
* Added "Compressed Carbon -> Carbon" recipe to the Ore Crusher
* Added "Carbon -> Coal" recipe to the Ore Crusher
* Added Iron Golem Assembler
* Added Reinforced Cloth * Added Reinforced Cloth
* Added Bee protection to Hazmat Suit * Added Bee protection to Hazmat Suit
* Added Enchantment Rune * Added Enchantment Rune
* Added Tape Measure * Added Tape Measure
* Added "Bone Block -> Bone meal" recipe to the Grind Stone
* Added Iron Golem Assembler
#### Changes #### Changes
* Refactored and reworked the Generator API * Refactored and reworked the Generator API

View File

@ -159,6 +159,10 @@ All of the collected data is publicly accessible: https://bstats.org/plugin/bukk
You can also disable this behaviour under `/plugins/bStats/config.yml`.<br> You can also disable this behaviour under `/plugins/bStats/config.yml`.<br>
For more info see [bStats' Privacy Policy](https://bstats.org/privacy-policy) For more info see [bStats' Privacy Policy](https://bstats.org/privacy-policy)
Our [bStats Module](https://github.com/Slimefun/MetricsModule) is downloaded automatically when installing this Plugin, this module will automatically update on server starts independently from the main plugin. This way we can automatically roll out updates to the bStats module, in cases of severe performance issues for example where live data and insight into what is impacting performance can be crucial.
These updates can of course be disabled under `/plugins/Slimefun/config.yml`. To disable metrics collection as a whole, see the paragraph above.
</details> </details>
<details> <details>

11
pom.xml
View File

@ -327,6 +327,17 @@
<version>1.7</version> <version>1.7</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-java</artifactId>
<version>3.8.06</version>
<exclusions>
<exclusion>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency> <dependency>
<groupId>io.papermc</groupId> <groupId>io.papermc</groupId>
<artifactId>paperlib</artifactId> <artifactId>paperlib</artifactId>

View File

@ -2,17 +2,16 @@ package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
import java.util.Collection; import java.util.Collection;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.plugin.Plugin;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors; import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.reflection.ReflectionUtils; import io.github.thebusybiscuit.cscorelib2.reflection.ReflectionUtils;
import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand; import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand;
import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand; import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.plugin.Plugin;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
class VersionsCommand extends SubCommand { class VersionsCommand extends SubCommand {
@ -42,8 +41,11 @@ class VersionsCommand extends SubCommand {
sender.sendMessage(ChatColors.color("&aCS-CoreLib &2v" + SlimefunPlugin.getCSCoreLibVersion())); sender.sendMessage(ChatColors.color("&aCS-CoreLib &2v" + SlimefunPlugin.getCSCoreLibVersion()));
sender.sendMessage(ChatColors.color("&aSlimefun &2v" + SlimefunPlugin.getVersion())); sender.sendMessage(ChatColors.color("&aSlimefun &2v" + SlimefunPlugin.getVersion()));
if (SlimefunPlugin.getMetricsService().getVersion() != null)
sender.sendMessage(ChatColors.color("&aMetrics: &2#" + SlimefunPlugin.getMetricsService().getVersion() + ')'));
if (SlimefunPlugin.getRegistry().isBackwardsCompatible()) { if (SlimefunPlugin.getRegistry().isBackwardsCompatible()) {
sender.sendMessage(ChatColor.YELLOW + "Backwards compatiblity enabled!"); sender.sendMessage(ChatColor.YELLOW + "Backwards compatibility enabled!");
} }
sender.sendMessage(""); sender.sendMessage("");

View File

@ -0,0 +1,242 @@
package io.github.thebusybiscuit.slimefun4.core.services;
import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
import kong.unirest.HttpResponse;
import kong.unirest.JsonNode;
import kong.unirest.Unirest;
import kong.unirest.UnirestException;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import org.bukkit.plugin.Plugin;
/**
* This Class represents a Metrics Service that sends data to https://bstats.org/
* This data is used to analyse the usage of this {@link Plugin}.
* <p>
* You can find more info in the README file of this Project on GitHub. <br>
* <b>Note:</b> To start the metrics you will need to be calling {@link #start()}
*
* @author WalshyDev
*/
public class MetricsService {
private static final String REPO_NAME = "MetricsModule";
private static final String GH_API = "https://api.github.com/repos/Slimefun/" + REPO_NAME;
private static final String GH_RELEASES = "https://github.com/Slimefun/" + REPO_NAME + "/releases/download";
private final SlimefunPlugin plugin;
private final File parentFolder;
private final File metricsModuleFile;
private URLClassLoader moduleClassLoader;
private String metricVersion = null;
private boolean hasDownloadedUpdate = false;
static {
Unirest.config()
.concurrency(2, 1)
.setDefaultHeader("User-Agent", "MetricsModule Auto-Updater")
.setDefaultHeader("Accept", "application/vnd.github.v3+json")
.enableCookieManagement(false)
.cookieSpec("ignoreCookies");
}
public MetricsService(SlimefunPlugin plugin) {
this.plugin = plugin;
this.parentFolder = new File(plugin.getDataFolder(), "cache" + File.separatorChar + "modules");
if (!parentFolder.exists()) {
parentFolder.mkdirs();
}
this.metricsModuleFile = new File(parentFolder, REPO_NAME + ".jar");
}
/**
* This method loads the metric module and starts the metrics collection.
*/
public void start() {
if (!metricsModuleFile.exists()) {
plugin.getLogger().info(REPO_NAME + " does not exist, downloading...");
if (!download(getLatestVersion())) {
plugin.getLogger().warning("Failed to start metrics as the file could not be downloaded.");
return;
}
}
try {
// Load the jar file into a child class loader using the SF PluginClassLoader
// as a parent.
moduleClassLoader = URLClassLoader.newInstance(new URL[] { metricsModuleFile.toURI().toURL() },
plugin.getClass().getClassLoader());
Class<?> cl = moduleClassLoader.loadClass("dev.walshy.sfmetrics.MetricsModule");
metricVersion = cl.getPackage().getImplementationVersion();
// If it has not been newly downloaded, auto-updates are on AND there's a new version
// then cleanup, download and start
if (!hasDownloadedUpdate && hasAutoUpdates() && checkForUpdate(metricVersion)
) {
plugin.getLogger().info("Cleaning up and re-loading Metrics.");
cleanUp();
start();
return;
}
// Finally, we're good to start this.
Method start = cl.getDeclaredMethod("start");
String version = cl.getPackage().getImplementationVersion();
// This is required to be sync due to bStats.
Slimefun.runSync(() -> {
try {
start.invoke(null);
plugin.getLogger().info("Metrics build #" + version + " started.");
} catch (Exception e) {
plugin.getLogger().log(Level.WARNING, "Failed to start metrics.", e);
}
});
} catch (Exception e) {
plugin.getLogger().log(Level.WARNING,
"Failed to load the metrics module. Maybe the jar is corrupt?", e);
}
}
/**
* This will close the child classloader and mark all the resources held under this no longer
* in use, they will be cleaned up the next GC run.
*/
public void cleanUp() {
try {
if (this.moduleClassLoader != null) {
this.moduleClassLoader.close();
}
} catch (IOException e) {
plugin.getLogger().log(Level.WARNING,
"Could not clean up module class loader. Some memory may have been leaked.");
}
}
/**
* Checks for a new update and compares it against the current version.
* If there is a new version available then this returns true.
*
* @param currentVersion The current version which is being used.
* @return True if there is an update available.
*/
public boolean checkForUpdate(String currentVersion) {
if (currentVersion == null || !PatternUtils.NUMERIC.matcher(currentVersion).matches()) {
return false;
}
int latest = getLatestVersion();
if (latest > Integer.parseInt(currentVersion)) {
return download(latest);
}
return false;
}
/**
* Gets the latest version available as an int.
* This is an internal method used by {@link #checkForUpdate(String)}.
* If it cannot get the version for whatever reason this will return 0, effectively always
* being behind.
*
* @return The latest version as an integer or -1 if it failed to fetch.
*/
private int getLatestVersion() {
try {
HttpResponse<JsonNode> response = Unirest.get(GH_API + "/releases/latest")
.asJson();
if (!response.isSuccess()) return -1;
JsonNode node = response.getBody();
if (node == null) return -1;
return node.getObject().getInt("tag_name");
} catch (UnirestException e) {
plugin.getLogger().log(Level.SEVERE, "Failed to fetch latest builds for SFMetrics");
return -1;
}
}
/**
* Downloads the version specified to Slimefun's data folder.
*
* @param version The version to download.
*/
private boolean download(int version) {
File f = new File(parentFolder, "Metrics-" + version + ".jar");
try {
plugin.getLogger().log(Level.INFO, "# Starting download of MetricsModule build: #{0}", version);
AtomicInteger lastPercentPosted = new AtomicInteger();
HttpResponse<File> response = Unirest.get(GH_RELEASES + "/" + version
+ "/" + REPO_NAME + ".jar")
.downloadMonitor((b, fileName, bytesWritten, totalBytes) -> {
int percent = (int) (20 * (Math.round((((double) bytesWritten / totalBytes) * 100) / 20)));
if (percent != 0 && percent != lastPercentPosted.get()) {
plugin.getLogger().info("# Downloading... " + percent + "% " +
"(" + bytesWritten + "/" + totalBytes + " bytes)");
lastPercentPosted.set(percent);
}
})
.asFile(f.getPath());
if (response.isSuccess()) {
plugin.getLogger().log(Level.INFO, "Successfully downloaded {0} build: #{1}", new Object[] {REPO_NAME, version});
// Replace the metric file with the new one
Files.move(f.toPath(), metricsModuleFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
metricVersion = String.valueOf(version);
hasDownloadedUpdate = true;
return true;
}
} catch (UnirestException e) {
plugin.getLogger().log(Level.WARNING, "Failed to fetch the latest jar file from the" +
" builds page. Perhaps GitHub is down.");
} catch (IOException e) {
plugin.getLogger().log(Level.WARNING, "Failed to replace the old metric file with the " +
"new one. Please do this manually! Error: {0}", e.getMessage());
}
return false;
}
/**
* Returns the currently downloaded metrics version.
* This <strong>can change</strong>! It may be null or an
* older version before it has downloaded a newer one.
*
* @return The current version or null if not loaded.
*/
@Nullable
public String getVersion() {
return metricVersion;
}
/**
* Returns if the current server has metrics auto-updates enabled.
*
* @return True if the current server has metrics auto-updates enabled.
*/
public boolean hasAutoUpdates() {
return SlimefunPlugin.instance().getConfig().getBoolean("metrics.auto-update");
}
}

View File

@ -6,10 +6,9 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import com.google.gson.JsonArray; import kong.unirest.JsonNode;
import com.google.gson.JsonElement; import kong.unirest.json.JSONArray;
import com.google.gson.JsonObject; import kong.unirest.json.JSONObject;
import me.mrCookieSlime.Slimefun.api.Slimefun; import me.mrCookieSlime.Slimefun.api.Slimefun;
class ContributionsConnector extends GitHubConnector { class ContributionsConnector extends GitHubConnector {
@ -57,10 +56,10 @@ class ContributionsConnector extends GitHubConnector {
} }
@Override @Override
public void onSuccess(JsonElement element) { public void onSuccess(JsonNode element) {
finished = true; finished = true;
if (element.isJsonArray()) { if (element.isArray()) {
computeContributors(element.getAsJsonArray()); computeContributors(element.getArray());
} }
else { else {
Slimefun.getLogger().log(Level.WARNING, "Received an unusual answer from GitHub, possibly a timeout? ({0})", element); Slimefun.getLogger().log(Level.WARNING, "Received an unusual answer from GitHub, possibly a timeout? ({0})", element);
@ -82,13 +81,13 @@ class ContributionsConnector extends GitHubConnector {
return "/contributors?per_page=100&page=" + page; return "/contributors?per_page=100&page=" + page;
} }
private void computeContributors(JsonArray array) { private void computeContributors(JSONArray array) {
for (int i = 0; i < array.size(); i++) { for (int i = 0; i < array.length(); i++) {
JsonObject object = array.get(i).getAsJsonObject(); JSONObject object = array.getJSONObject(i);
String name = object.get("login").getAsString(); String name = object.getString("login");
int commits = object.get("contributions").getAsInt(); int commits = object.getInt("contributions");
String profile = object.get("html_url").getAsString(); String profile = object.getString("html_url");
if (!blacklist.contains(name)) { if (!blacklist.contains(name)) {
github.addContributor(aliases.getOrDefault(name, name), profile, role, commits); github.addContributor(aliases.getOrDefault(name, name), profile, role, commits);

View File

@ -6,17 +6,14 @@ import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.logging.Level; import java.util.logging.Level;
import com.google.gson.JsonElement; import kong.unirest.HttpResponse;
import com.google.gson.JsonParser; import kong.unirest.JsonNode;
import kong.unirest.Unirest;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import kong.unirest.UnirestException;
import kong.unirest.json.JSONException;
import me.mrCookieSlime.Slimefun.api.Slimefun; import me.mrCookieSlime.Slimefun.api.Slimefun;
abstract class GitHubConnector { abstract class GitHubConnector {
@ -34,7 +31,7 @@ abstract class GitHubConnector {
public abstract String getURLSuffix(); public abstract String getURLSuffix();
public abstract void onSuccess(JsonElement element); public abstract void onSuccess(JsonNode element);
public void onFailure() { public void onFailure() {
// Don't do anything by default // Don't do anything by default
@ -48,58 +45,54 @@ abstract class GitHubConnector {
} }
try { try {
URL website = new URL("https://api.github.com/repos/" + repository + getURLSuffix()); HttpResponse<JsonNode> resp = Unirest.get("https://api.github.com/repos/" + repository + getURLSuffix())
.header("User-Agent", "Slimefun4 (https://github.com/Slimefun)")
.asJson();
URLConnection connection = website.openConnection(); if (resp.isSuccess()) {
connection.setConnectTimeout(8000); onSuccess(resp.getBody());
connection.addRequestProperty("Accept-Charset", "UTF-8"); writeCacheFile(resp.getBody());
connection.addRequestProperty("User-Agent", "Slimefun 4 GitHub Agent (by TheBusyBiscuit)"); }
connection.setDoOutput(true); else {
Slimefun.getLogger().log(Level.WARNING, "Failed to fetch {0}", repository + getURLSuffix());
try (ReadableByteChannel channel = Channels.newChannel(connection.getInputStream())) {
try (FileOutputStream stream = new FileOutputStream(file)) {
stream.getChannel().transferFrom(channel, 0, Long.MAX_VALUE);
parseData();
} }
} }
} catch (UnirestException e) {
catch (IOException e) {
if (github.isLoggingEnabled()) { if (github.isLoggingEnabled()) {
Slimefun.getLogger().log(Level.WARNING, "Could not connect to GitHub in time."); Slimefun.getLogger().log(Level.WARNING, "Could not connect to GitHub in time.");
} }
if (hasData()) { // It has the cached file, let's just read that then
parseData(); if (file.exists()) {
JsonNode cache = readCacheFile();
if (cache != null) {
onSuccess(cache);
return;
} }
else { }
// If the request failed and it failed to read the cache then call onFailure.
onFailure(); onFailure();
} }
} }
private JsonNode readCacheFile() {
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {
return new JsonNode(br.readLine());
}
catch (IOException | JSONException e) {
Slimefun.getLogger().log(Level.WARNING, "Failed to read Github cache file: {0}", file.getName());
return null;
}
} }
public boolean hasData() { private void writeCacheFile(JsonNode node) {
return getFile().exists(); try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(node.toString().getBytes(StandardCharsets.UTF_8));
} }
catch (IOException e) {
public File getFile() { Slimefun.getLogger().log(Level.WARNING, "Failed to populate GitHub cache");
return file;
}
public void parseData() {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(getFile()), StandardCharsets.UTF_8))) {
StringBuilder builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
JsonElement element = new JsonParser().parse(builder.toString());
onSuccess(element);
}
catch (IOException x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Error occurred while parsing GitHub-Data for Slimefun " + SlimefunPlugin.getVersion());
onFailure();
} }
} }
} }

View File

@ -2,10 +2,9 @@ package io.github.thebusybiscuit.slimefun4.core.services.github;
import java.util.logging.Level; import java.util.logging.Level;
import com.google.gson.JsonArray; import kong.unirest.JsonNode;
import com.google.gson.JsonElement; import kong.unirest.json.JSONArray;
import com.google.gson.JsonObject; import kong.unirest.json.JSONObject;
import me.mrCookieSlime.Slimefun.api.Slimefun; import me.mrCookieSlime.Slimefun.api.Slimefun;
class GitHubIssuesTracker extends GitHubConnector { class GitHubIssuesTracker extends GitHubConnector {
@ -25,15 +24,15 @@ class GitHubIssuesTracker extends GitHubConnector {
} }
@Override @Override
public void onSuccess(JsonElement element) { public void onSuccess(JsonNode element) {
if (element.isJsonArray()) { if (element.isArray()) {
JsonArray array = element.getAsJsonArray(); JSONArray array = element.getArray();
int issues = 0; int issues = 0;
int pullRequests = 0; int pullRequests = 0;
for (JsonElement elem : array) { for (int i = 0; i < array.length(); i++) {
JsonObject obj = elem.getAsJsonObject(); JSONObject obj = array.getJSONObject(i);
if (obj.has("pull_request")) { if (obj.has("pull_request")) {
pullRequests++; pullRequests++;

View File

@ -9,14 +9,13 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.github.thebusybiscuit.cscorelib2.config.Config; import io.github.thebusybiscuit.cscorelib2.config.Config;
import io.github.thebusybiscuit.slimefun4.core.services.localization.Translators; import io.github.thebusybiscuit.slimefun4.core.services.localization.Translators;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture; import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils; import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import kong.unirest.JsonNode;
import kong.unirest.json.JSONObject;
/** /**
* This Service is responsible for grabbing every {@link Contributor} to this project * This Service is responsible for grabbing every {@link Contributor} to this project
@ -108,11 +107,11 @@ public class GitHubService {
connectors.add(new GitHubConnector(this, repository) { connectors.add(new GitHubConnector(this, repository) {
@Override @Override
public void onSuccess(JsonElement element) { public void onSuccess(JsonNode element) {
JsonObject object = element.getAsJsonObject(); JSONObject object = element.getObject();
forks = object.get("forks").getAsInt(); forks = object.getInt("forks");
stars = object.get("stargazers_count").getAsInt(); stars = object.getInt("stargazers_count");
lastUpdate = NumberUtils.parseGitHubDate(object.get("pushed_at").getAsString()); lastUpdate = NumberUtils.parseGitHubDate(object.getString("pushed_at"));
} }
@Override @Override

View File

@ -1,27 +0,0 @@
package io.github.thebusybiscuit.slimefun4.core.services.metrics;
import java.util.HashMap;
import java.util.Map;
import org.bstats.bukkit.Metrics.AdvancedPie;
import org.bukkit.plugin.Plugin;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class AddonsChart extends AdvancedPie {
AddonsChart() {
super("installed_addons", () -> {
Map<String, Integer> addons = new HashMap<>();
for (Plugin plugin : SlimefunPlugin.getInstalledAddons()) {
if (plugin.isEnabled()) {
addons.put(plugin.getName(), 1);
}
}
return addons;
});
}
}

View File

@ -1,16 +0,0 @@
package io.github.thebusybiscuit.slimefun4.core.services.metrics;
import org.bstats.bukkit.Metrics.SimplePie;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class AutoUpdaterChart extends SimplePie {
AutoUpdaterChart() {
super("auto_updates", () -> {
boolean enabled = SlimefunPlugin.getUpdater().isEnabled();
return enabled ? "enabled" : "disabled";
});
}
}

View File

@ -1,25 +0,0 @@
package io.github.thebusybiscuit.slimefun4.core.services.metrics;
import java.util.HashMap;
import java.util.Map;
import org.bstats.bukkit.Metrics.AdvancedPie;
import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class CommandChart extends AdvancedPie {
CommandChart() {
super("commands_ran", () -> {
Map<String, Integer> commands = new HashMap<>();
for (Map.Entry<SubCommand, Integer> entry : SlimefunPlugin.getCommand().getCommandUsage().entrySet()) {
commands.put("/sf " + entry.getKey().getName(), entry.getValue());
}
return commands;
});
}
}

View File

@ -1,16 +0,0 @@
package io.github.thebusybiscuit.slimefun4.core.services.metrics;
import org.bstats.bukkit.Metrics.SimplePie;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class CompatibilityModeChart extends SimplePie {
CompatibilityModeChart() {
super("compatibility_mode", () -> {
boolean enabled = SlimefunPlugin.getRegistry().isBackwardsCompatible();
return enabled ? "enabled" : "disabled";
});
}
}

View File

@ -1,17 +0,0 @@
package io.github.thebusybiscuit.slimefun4.core.services.metrics;
import org.bstats.bukkit.Metrics.SimplePie;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class GuideLayoutChart extends SimplePie {
GuideLayoutChart() {
super("guide_layout", () -> {
boolean book = SlimefunPlugin.getCfg().getBoolean("guide.default-view-book");
return book ? "Book" : "Chest GUI";
});
}
}

View File

@ -1,55 +0,0 @@
package io.github.thebusybiscuit.slimefun4.core.services.metrics;
import org.bstats.bukkit.Metrics;
import org.bukkit.plugin.Plugin;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
/**
* This Class represents a Metrics Service that sends data to https://bstats.org/
* This data is used to analyse the usage of this {@link Plugin}.
*
* You can find more info in the README file of this Project on GitHub.
*
* @author TheBusyBiscuit
*
*/
public class MetricsService {
private final SlimefunPlugin plugin;
/**
* This creates a new {@link MetricsService}. The constructor does not set up
* anything related to bStats yet, that happens in the {@link MetricsService#start()} method.
*
* @param plugin
* The instance of our {@link SlimefunPlugin}
*/
public MetricsService(SlimefunPlugin plugin) {
this.plugin = plugin;
}
/**
* This method intializes and starts the metrics collection.
*/
public void start() {
Metrics metrics = new Metrics(plugin, 4574);
if (SlimefunPlugin.getUpdater().getBranch().isOfficial()) {
// We really do not need this data if it is an unofficially modified build...
metrics.addCustomChart(new AutoUpdaterChart());
}
metrics.addCustomChart(new ResourcePackChart());
metrics.addCustomChart(new SlimefunVersionChart());
metrics.addCustomChart(new ServerLanguageChart());
metrics.addCustomChart(new PlayerLanguageChart());
metrics.addCustomChart(new ResearchesEnabledChart());
metrics.addCustomChart(new GuideLayoutChart());
metrics.addCustomChart(new AddonsChart());
metrics.addCustomChart(new CommandChart());
metrics.addCustomChart(new ServerSizeChart());
metrics.addCustomChart(new CompatibilityModeChart());
}
}

View File

@ -1,31 +0,0 @@
package io.github.thebusybiscuit.slimefun4.core.services.metrics;
import java.util.HashMap;
import java.util.Map;
import org.bstats.bukkit.Metrics.AdvancedPie;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import io.github.thebusybiscuit.slimefun4.core.services.localization.Language;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class PlayerLanguageChart extends AdvancedPie {
PlayerLanguageChart() {
super("player_languages", () -> {
Map<String, Integer> languages = new HashMap<>();
for (Player p : Bukkit.getOnlinePlayers()) {
Language language = SlimefunPlugin.getLocalization().getLanguage(p);
boolean supported = SlimefunPlugin.getLocalization().isLanguageLoaded(language.getId());
String lang = supported ? language.getId() : "Unsupported Language";
languages.merge(lang, 1, Integer::sum);
}
return languages;
});
}
}

View File

@ -1,16 +0,0 @@
package io.github.thebusybiscuit.slimefun4.core.services.metrics;
import org.bstats.bukkit.Metrics.SimplePie;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class ResearchesEnabledChart extends SimplePie {
ResearchesEnabledChart() {
super("servers_with_researches_enabled", () -> {
boolean enabled = SlimefunPlugin.getRegistry().isFreeCreativeResearchingEnabled();
return enabled ? "enabled" : "disabled";
});
}
}

View File

@ -1,25 +0,0 @@
package io.github.thebusybiscuit.slimefun4.core.services.metrics;
import org.bstats.bukkit.Metrics.SimplePie;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class ResourcePackChart extends SimplePie {
ResourcePackChart() {
super("resourcepack", () -> {
String version = SlimefunPlugin.getItemTextureService().getVersion();
if (version != null && version.startsWith("v")) {
return version + " (Official)";
}
else if (SlimefunPlugin.getItemTextureService().isActive()) {
return "Custom / Modified";
}
else {
return "None";
}
});
}
}

View File

@ -1,18 +0,0 @@
package io.github.thebusybiscuit.slimefun4.core.services.metrics;
import org.bstats.bukkit.Metrics.SimplePie;
import io.github.thebusybiscuit.slimefun4.core.services.localization.Language;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class ServerLanguageChart extends SimplePie {
ServerLanguageChart() {
super("language", () -> {
Language language = SlimefunPlugin.getLocalization().getDefaultLanguage();
boolean supported = SlimefunPlugin.getLocalization().isLanguageLoaded(language.getId());
return supported ? language.getId() : "Unsupported Language";
});
}
}

View File

@ -1,40 +0,0 @@
package io.github.thebusybiscuit.slimefun4.core.services.metrics;
import org.bstats.bukkit.Metrics.SimplePie;
import org.bukkit.Bukkit;
class ServerSizeChart extends SimplePie {
ServerSizeChart() {
super("server_size", () -> {
int players = Bukkit.getOnlinePlayers().size();
if (players < 10) {
return "0-10";
}
if (players < 25) {
return "10-25";
}
if (players < 50) {
return "25-50";
}
if (players < 100) {
return "50-100";
}
if (players < 200) {
return "100-200";
}
if (players < 300) {
return "200-300";
}
return "300+";
});
}
}

View File

@ -1,24 +0,0 @@
package io.github.thebusybiscuit.slimefun4.core.services.metrics;
import java.util.HashMap;
import java.util.Map;
import org.bstats.bukkit.Metrics.DrilldownPie;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class SlimefunVersionChart extends DrilldownPie {
SlimefunVersionChart() {
super("slimefun_version", () -> {
Map<String, Map<String, Integer>> outerMap = new HashMap<>();
Map<String, Integer> innerMap = new HashMap<>();
innerMap.put(SlimefunPlugin.getVersion(), 1);
outerMap.put(SlimefunPlugin.getUpdater().getBranch().getName(), innerMap);
return outerMap;
});
}
}

View File

@ -1,4 +0,0 @@
/**
* This package contains everything related to bStats Metrics
*/
package io.github.thebusybiscuit.slimefun4.core.services.metrics;

View File

@ -41,7 +41,7 @@ import io.github.thebusybiscuit.slimefun4.core.services.PerWorldSettingsService;
import io.github.thebusybiscuit.slimefun4.core.services.PermissionsService; import io.github.thebusybiscuit.slimefun4.core.services.PermissionsService;
import io.github.thebusybiscuit.slimefun4.core.services.UpdaterService; import io.github.thebusybiscuit.slimefun4.core.services.UpdaterService;
import io.github.thebusybiscuit.slimefun4.core.services.github.GitHubService; import io.github.thebusybiscuit.slimefun4.core.services.github.GitHubService;
import io.github.thebusybiscuit.slimefun4.core.services.metrics.MetricsService; import io.github.thebusybiscuit.slimefun4.core.services.MetricsService;
import io.github.thebusybiscuit.slimefun4.core.services.plugins.ThirdPartyPluginService; import io.github.thebusybiscuit.slimefun4.core.services.plugins.ThirdPartyPluginService;
import io.github.thebusybiscuit.slimefun4.core.services.profiler.SlimefunProfiler; import io.github.thebusybiscuit.slimefun4.core.services.profiler.SlimefunProfiler;
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientAltar; import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientAltar;
@ -197,7 +197,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
networkManager = new NetworkManager(networkSize); networkManager = new NetworkManager(networkSize);
// Setting up bStats // Setting up bStats
metricsService.start(); new Thread(metricsService::start).start();
// Starting the Auto-Updater // Starting the Auto-Updater
if (config.getBoolean("options.auto-update")) { if (config.getBoolean("options.auto-update")) {
@ -368,6 +368,8 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
// Create a new backup zip // Create a new backup zip
backupService.run(); backupService.run();
metricsService.cleanUp();
// Prevent Memory Leaks // Prevent Memory Leaks
// These static Maps should be removed at some point... // These static Maps should be removed at some point...
AContainer.processing = null; AContainer.processing = null;
@ -570,6 +572,16 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
return instance.updaterService; return instance.updaterService;
} }
/**
* This method returns the {@link MetricsService} of Slimefun.
* It is used to handle sending metric information to bStats.
*
* @return The {@link MetricsService} for Slimefun
*/
public static MetricsService getMetricsService() {
return instance.metricsService;
}
/** /**
* This method returns the {@link GitHubService} of Slimefun. * This method returns the {@link GitHubService} of Slimefun.
* It is used to retrieve data from GitHub repositories. * It is used to retrieve data from GitHub repositories.

View File

@ -46,8 +46,6 @@ public class CargoManager extends SlimefunItem {
}, new BlockUseHandler() { }, new BlockUseHandler() {
private final String visualizerKey = "visualizer";
@Override @Override
public void onRightClick(PlayerRightClickEvent e) { public void onRightClick(PlayerRightClickEvent e) {
Optional<Block> block = e.getClickedBlock(); Optional<Block> block = e.getClickedBlock();
@ -56,12 +54,12 @@ public class CargoManager extends SlimefunItem {
Player p = e.getPlayer(); Player p = e.getPlayer();
Block b = block.get(); Block b = block.get();
if (BlockStorage.getLocationInfo(b.getLocation(), visualizerKey) == null) { if (BlockStorage.getLocationInfo(b.getLocation(), "visualizer") == null) {
BlockStorage.addBlockInfo(b, visualizerKey, "disabled"); BlockStorage.addBlockInfo(b, "visualizer", "disabled");
p.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cCargo Net Visualizer: " + "&4\u2718")); p.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cCargo Net Visualizer: " + "&4\u2718"));
} }
else { else {
BlockStorage.addBlockInfo(b, visualizerKey, null); BlockStorage.addBlockInfo(b, "visualizer", null);
p.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cCargo Net Visualizer: " + "&2\u2714")); p.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cCargo Net Visualizer: " + "&2\u2714"));
} }
} }

View File

@ -50,6 +50,12 @@ public class OreCrusher extends MultiBlockMachine {
recipes.add(new ItemStack(Material.MAGMA_BLOCK, 4)); recipes.add(new ItemStack(Material.MAGMA_BLOCK, 4));
recipes.add(SlimefunItems.SULFATE); recipes.add(SlimefunItems.SULFATE);
recipes.add(SlimefunItems.CARBON);
recipes.add(new ItemStack(Material.COAL, 8));
recipes.add(SlimefunItems.COMPRESSED_CARBON);
recipes.add(new SlimefunItemStack(SlimefunItems.CARBON, 4));
} }
public boolean isOreDoublingEnabled() { public boolean isOreDoublingEnabled() {

View File

@ -1,15 +0,0 @@
package me.mrCookieSlime.Slimefun.Objects;
import org.bukkit.NamespacedKey;
/**
* @deprecated Moved to io.github.thebusybiscuit.slimefun4.core.researching.Research
*
*/
@Deprecated
public class Research extends io.github.thebusybiscuit.slimefun4.core.researching.Research {
public Research(NamespacedKey key, int id, String name, int cost) {
super(key, id, name, cost);
}
}

View File

@ -1,27 +0,0 @@
package me.mrCookieSlime.Slimefun.Objects.SlimefunItem;
import org.bukkit.inventory.ItemStack;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
* @deprecated Moved to {@link io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem}
*
* @param <T>
* deprecated.
*/
@Deprecated
public abstract class SimpleSlimefunItem<T extends ItemHandler> extends io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem<T> {
public SimpleSlimefunItem(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
}
public SimpleSlimefunItem(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
super(category, item, recipeType, recipe, recipeOutput);
}
}

View File

@ -1,9 +0,0 @@
package me.mrCookieSlime.Slimefun.Objects.handlers;
/**
* @deprecated Moved to {@link io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler}
*/
@Deprecated
public interface ItemUseHandler extends io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler {
}

View File

@ -6,7 +6,7 @@ options:
auto-update: true auto-update: true
backwards-compatibility: true backwards-compatibility: true
chat-prefix: '&a&lSlimefun 4 &7>' chat-prefix: '&a&lSlimefun 4&7> '
armor-update-interval: 10 armor-update-interval: 10
enable-armor-effects: true enable-armor-effects: true
auto-save-delay-in-minutes: 10 auto-save-delay-in-minutes: 10
@ -40,6 +40,9 @@ items:
backpacks: true backpacks: true
soulbound: true soulbound: true
metrics:
auto-update: true
research-ranks: research-ranks:
- Chicken - Chicken
- Cow - Cow

View File

@ -23,3 +23,4 @@ slimefun:
easter: Húsvét (Április) easter: Húsvét (Április)
birthday: TheBusyBiscuit születésnapja (Október 26.) birthday: TheBusyBiscuit születésnapja (Október 26.)
halloween: Halloween (Október 31.) halloween: Halloween (Október 31.)
androids: Programozható Androidok

View File

@ -1,145 +1,107 @@
--- ---
minecraft:
blasting:
lore:
- Olvaszd meg ezt a tárgyat egy Kohóban,
- hogy elkészítsd a kívánt tárgyat
name: Kohó Recept
campfire:
lore:
- Olvaszd meg ezt a tárgyat egy Tábortűzön,
- hogy elkészítsd a kívánt tárgyat
name: Tábortűz Recept
furnace:
lore:
- Olvaszd meg ezt a tárgyat egy Kemencében,
- hogy elkészítsd a kívánt tárgyat
name: Kemence Recept
shaped:
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Normális Barkácsasztal segítségével.
- A forma fontos.
name: Barkácsrecept Forma
shapeless:
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Normális Barkácsasztal segítségével.
- Ez a Recept forma nélküli.
name: Forma Nélküli Barkácsrecept
smoking:
lore:
- Olvaszd meg ezt a tárgyat egy Füstölőben,
- hogy elkészítsd a kívánt tárgyat
name: Füstölő Recept
stonecutting:
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Kővágó segítségével
name: Kővágó Recept
slimefun: slimefun:
ancient_altar: multiblock:
name: Multiblock
lore: lore:
- Készítsd el ezt a Tárgyat az ábra alapján - Építsd meg a látott szerkezetet
- egy Ancient Altar segítségével. - az ábra alapján. Ez nem barkácsolás.
- Keress utána az Ancient Altar-nak a további információkért
name: Ancient Altar
armor_forge:
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Armor Forge segítségével
name: Armor Forge
compressor:
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Compressor segítségével
name: Compressor
enhanced_crafting_table: enhanced_crafting_table:
name: Enhanced Crafting Table
lore: lore:
- Készítsd el ezt a Tárgyat az ábra alapján - Készítsd el ezt a Tárgyat az ábra alapján
- egy Enhanced Crafting Table-ben. - egy Enhanced Crafting Table-ben.
- A normális Barkácsasztal nem lesz elegendő! - A normális Barkácsasztal nem lesz elegendő!
name: Enhanced Crafting Table armor_forge:
food_composter: name: Armor Forge
lore: lore:
- Készítsd el ezt a Tárgyat az ábra alapján - Készítsd el ezt a Tárgyat az ábra alapján
- egy Food Composter segítségével - egy Armor Forge segítségével
name: Food Composter
food_fabricator:
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Food Fabricator segítségével
name: Food Fabricator
freezer:
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Freezer segítségével
name: Freezer
geo_miner:
lore:
- Ez a tárgy összegyűjthető
- egy GEO Miner segítségével
name: GEO Miner
gold_pan:
lore:
- Használd az Gold Pan-t,
- hogy megszerezd ezt a tárgyat
name: Gold Pan
grind_stone: grind_stone:
name: Grind Stone
lore: lore:
- Készítsd el ezt a Tárgyat az ábra alapján - Készítsd el ezt a Tárgyat az ábra alapján
- egy Grind Stone segítségével - egy Grind Stone segítségével
name: Grind Stone
heated_pressure_chamber:
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Heated Pressure Chamber segítségével
name: Heated Pressure Chamber
juicer:
lore:
- Készítsd el ezt a Gyümölcslevet az ábra alapján
- egy Juicer segítségével
name: Juicer
magic_workbench:
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Magic Workbench segítségével
name: Magic Workbench
mob_drop:
lore:
- Öld meg ezt az Élőlényt,
- hogy megszerezd ezt a tárgyat
name: Mob Drop
multiblock:
lore:
- Építsd meg a látott szerkezetet
- az ábra alapján. Ez nem barkácsolás.
name: Multiblock
nuclear_reactor:
lore:
- Ez a tárgy mellékterméke
- a Nuclear Reactor működésének
name: Nuclear Reactor
ore_crusher:
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Ore Crusher segítségével
name: Ore Crusher
ore_washer:
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Ore Washer segítségével
name: Ore Washer
pressure_chamber:
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Pressure Chamber segítségével
name: Pressure Chamber
smeltery: smeltery:
name: Smeltery
lore: lore:
- Készítsd el ezt a Tárgyat az ábra alapján - Készítsd el ezt a Tárgyat az ábra alapján
- egy Smeltery segítségével - egy Smeltery segítségével
name: Smeltery ore_crusher:
name: Ore Crusher
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Ore Crusher segítségével
mob_drop:
name: Mob Drop
lore:
- Öld meg ezt az Élőlényt,
- hogy megszerezd ezt a tárgyat
gold_pan:
name: Gold Pan
lore:
- Használd az Gold Pan-t,
- hogy megszerezd ezt a tárgyat
compressor:
name: Compressor
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Compressor segítségével
pressure_chamber:
name: Pressure Chamber
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Pressure Chamber segítségével
ore_washer:
name: Ore Washer
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Ore Washer segítségével
juicer:
name: Juicer
lore:
- Készítsd el ezt a Gyümölcslevet az ábra alapján
- egy Juicer segítségével
magic_workbench:
name: Magic Workbench
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Magic Workbench segítségével
ancient_altar:
name: Ancient Altar
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Ancient Altar segítségével.
- Keress utána az Ancient Altar-nak a további információkért
heated_pressure_chamber:
name: Heated Pressure Chamber
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Heated Pressure Chamber segítségével
food_fabricator:
name: Food Fabricator
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Food Fabricator segítségével
food_composter:
name: Food Composter
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Food Composter segítségével
freezer:
name: Freezer
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Freezer segítségével
geo_miner:
name: GEO Miner
lore:
- Ez a tárgy összegyűjthető
- egy GEO Miner segítségével
nuclear_reactor:
name: Nuclear Reactor
lore:
- Ez a tárgy mellékterméke
- a Nuclear Reactor működésének
oil_pump: oil_pump:
name: Oil Pump name: Oil Pump
lore: lore:
@ -156,3 +118,46 @@ slimefun:
lore: lore:
- Készítsd el ezt a Tárgyat az ábra alapján - Készítsd el ezt a Tárgyat az ábra alapján
- egy Refinery segítségével - egy Refinery segítségével
minecraft:
shaped:
name: Barkácsrecept Forma
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Normális Barkácsasztal segítségével.
- A forma fontos.
shapeless:
name: Forma Nélküli Barkácsrecept
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Normális Barkácsasztal segítségével.
- Ez a Recept forma nélküli.
furnace:
name: Kemence Recept
lore:
- Olvaszd meg ezt a tárgyat egy Kemencében,
- hogy elkészítsd a kívánt tárgyat
blasting:
name: Kohó Recept
lore:
- Olvaszd meg ezt a tárgyat egy Kohóban,
- hogy elkészítsd a kívánt tárgyat
smoking:
name: Füstölő Recept
lore:
- Olvaszd meg ezt a tárgyat egy Füstölőben,
- hogy elkészítsd a kívánt tárgyat
campfire:
name: Tábortűz Recept
lore:
- Olvaszd meg ezt a tárgyat egy Tábortűzön,
- hogy elkészítsd a kívánt tárgyat
stonecutting:
name: Kővágó Recept
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Kővágó segítségével
smithing:
name: Kovácsasztal Recept
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Kovácsasztal segítségével

View File

@ -1,234 +1,238 @@
--- ---
slimefun: slimefun:
24k_gold_block: Aranyváros walking_sticks: Sétapálcák
advanced_android: Speciális Androidok portable_crafter: Hordozható Barkácsoló
advanced_butcher_android: Fejlett Androidok - Hentes fortune_cookie: Szerencsesüti
advanced_circuit_board: Fejlett Áramköri Lap portable_dustbin: Hordozható Kuka
advanced_electric_smeltery: Fejlett Elektromos Olvasztómű meat_jerky: Pácolt Hús
advanced_farmer_android: Fejlett Androidok - Farmer
advanced_fisherman_android: Fejlett Androidok - Halász
advanced_output_node: Speciális Kimeneti Csomópont
alloys: Speciális Ötvözetek
ancient_altar: Ősi Oltár
ancient_runes: Elemi Rúnák
android_interfaces: Android Csatlakozási Felületek
android_memory_core: Memóriamag
angel_talisman: Az Angyal Talizmánja
animal_growth_accelerator: Az állatok Növekedésének Manipulálása
anvil_talisman: Az Üllő Talizmánja
armored_jetboots: Páncélozott Sugárhajtású Csizmák
armored_jetpack: Páncélozott Jetpack
armor_forge: Páncél Barkácsolás armor_forge: Páncél Barkácsolás
auto_anvil: Automatikus Üllő glowstone_armor: Izzókő Páncél
auto_breeder: Automatizált Etetés lumps: Rögök és Varázslat
auto_drier: Egy Száraz Nap ender_backpack: Ender Hátizsák
auto_enchanting: Automatikus Fejlesztés és Fejlesztés Törlés ender_armor: Ender Páncél
automated_crafting_chamber: Automatizált Barkácsolás magic_eye_of_ender: Varázslatos Ender Szeme
automated_panning_machine: Automatizált Aranymosó magic_sugar: Varázscukor
automatic_ignition_chamber: Automatikus Gyújtókamra monster_jerky: Pácolt Szörnyhús
backpacks: Hátizsákok slime_armor: Nyálka Páncél
sword_of_beheading: Lefejezés Kardja
basic_circuit_board: Alapvető Áramköri Lap basic_circuit_board: Alapvető Áramköri Lap
advanced_circuit_board: Fejlett Áramköri Lap
smeltery: Kohó
steel: Acélkor
misc_power_items: Fontos energiával kapcsolatos tárgyak
battery: Az első Akkumulátorod battery: Az első Akkumulátorod
better_carbon_press: Továbbfejlesztett Szénprés steel_plate: Acéllemez
better_crop_growth_accelerator: Továbbfejlesztett Növény Növekedés Gyorsító steel_thruster: Acélhajtómű
better_electric_crucibles: Forró Olvasztótégelyek parachute: Ejtőernyő
better_electric_furnace: Továbbfejlesztett Elektromos Kemence grappling_hook: Vasmacska
better_food_fabricator: Továbbfejlesztett Élelmiszergyártás jetpacks: Jetpackek
better_freezer: Továbbfejlesztett Fagyasztó multitools: Többfunkciós Eszközök
better_gps_transmitters: Továbbfejlesztett Transzmitterek solar_panel_and_helmet: Napenergia
better_heated_pressure_chamber: Továbbfejlesztett Fűtött Nyomású Kamra elemental_staff: Elemi Pálcák
better_solar_generators: Továbbfejlesztett Napelemes Generátorok grind_stone: Köszörűkő
bio_reactor: Bioreaktor
blade_of_vampires: Vámpírok Pengéje
blistering_ingots: Hólyagos Radioaktivitás
block_placer: Blokk Lehelyező
boosted_uranium: Soha Véget Nem Érő Kör
boots_of_the_stomper: A Taposás Cipője
bound_armor: Lélekhez Kötött Páncél
bound_backpack: Lélekhez Kötött Tárolás
bound_tools: Lélélekhez Kötött Eszközök
bound_weapons: Lélekhez Kötött Fegyverek
bronze: Bronzkészítés
butcher_androids: Hentes Androidok
cactus_armor: Kaktusz Ruha cactus_armor: Kaktusz Ruha
capacitors: 1. Szintű Kondenzátorok gold_pan: Aranymosó
carbonado: Fekete Gyémántok magical_book_cover: Varázslatos Könyvkötés
carbonado_furnace: Karbonádó Szélű Kemence slimefun_metals: Új Fémek
carbonado_tools: Felső Szintű Gépek ore_crusher: Érc Duplázás
carbon_press: Szénprés bronze: Bronzkészítés
cargo_basics: Szállítmány Alapjai alloys: Speciális Ötvözetek
cargo_nodes: Szállítmány Beállítása
chainmail_armor: Lánc Páncél
charging_bench: Töltőpad
coal_generator: Széngenerátor
cobalt_pickaxe: Gyors Csákány
combustion_reactor: Égésreaktor
common_talisman: Gyakori Talizmán
composter: Föld Komposztáló
compressor_and_carbon: Szénkészítés compressor_and_carbon: Szénkészítés
cooler: Hordozható Italok gilded_iron_armor: Aranyozott Vaspáncél
copper_wire: Hígított Vezetőképesség synthetic_diamond: Szintetikus Gyémántok
crop_growth_accelerator: Növény Növekedés Gyorsító pressure_chamber: Nyomáskamra
crucible: Olvasztótégely synthetic_sapphire: Szintetikus Zafírok
crushed_ore: Ércek Tisztítása
damascus_steel: Damaszkuszi Acél damascus_steel: Damaszkuszi Acél
damascus_steel_armor: Damaszkuszi Acél Páncél damascus_steel_armor: Damaszkuszi Acél Páncél
diet_cookie: Diétás Süti reinforced_alloy: Megerősített Ötvözet
duct_tape: Szövetbetétes Ragasztószalag carbonado: Fekete Gyémántok
electric_crucible: Elektromos Olvasztótégely magic_workbench: Varázslatos Barkácsasztal
electric_furnaces: Erős Kemence wind_staff: Szél Pálca
electric_ingot_machines: Elektromos Öntvénygyártás reinforced_armor: Megerősített Páncél
ore_washer: Ércmosó
gold_carats: Tiszta Arany
silicon: Szilícium-völgy
fire_staff: Tűz Pálca
smelters_pickaxe: Olvasztó Csákány
common_talisman: Gyakori Talizmán
anvil_talisman: Az Üllő Talizmánja
miner_talisman: A Bányász Talizmánja
hunter_talisman: A Vadász Talizmánja
lava_talisman: A Láva Járó Talizmánja
water_talisman: A Vízlélegzés Talizmánja
angel_talisman: Az Angyal Talizmánja
fire_talisman: A Tűzoltó Talizmánja
lava_crystal: Tüzes Helyzet
magician_talisman: A Bűvész Talizmánja
traveller_talisman: Az Utazó Talizmánja
warrior_talisman: A Harcos Talizmánja
knight_talisman: A Lovag Talizmánja
gilded_iron: Fényes Vas
synthetic_emerald: Hamis Drágakő
chainmail_armor: Lánc Páncél
whirlwind_talisman: A Forgószél Talizmánja
wizard_talisman: A Varázsló Talizmánja
lumber_axe: Fadöntő Fejsze
hazmat_suit: Vegyvédelmi Ruha
uranium: Radioaktív
crushed_ore: Ércek Tisztítása
redstone_alloy: Redstone Ötvözet
carbonado_tools: Felső Szintű Gépek
first_aid: Elsősegély
gold_armor: Fényes Páncél
night_vision_googles: Éjjellátó Szemüvegek
pickaxe_of_containment: Csomagtartó Csákány
hercules_pickaxe: Herkules Csákány
table_saw: Asztali Fűrész
slime_steel_armor: Nyálkás Acél Páncél
blade_of_vampires: Vámpírok Pengéje
water_staff: Víz Pálca
24k_gold_block: Aranyváros
composter: Föld Komposztáló
farmer_shoes: Farmer Cipők
explosive_tools: Robbanóeszközök
automated_panning_machine: Automatizált Aranymosó
boots_of_the_stomper: A Taposás Cipője
pickaxe_of_the_seeker: A Kutatók Csákánya
backpacks: Hátizsákok
woven_backpack: Szőtt Hátizsák
crucible: Olvasztótégely
gilded_backpack: Aranyozott Hátizsák
armored_jetpack: Páncélozott Jetpack
ender_talismans: Ender Talizmánok
nickel_and_cobalt: Még több Érc
magnet: Mágneses Fémek
infused_magnet: Infúziós Mágnesek
cobalt_pickaxe: Gyors Csákány
essence_of_afterlife: Szellemidézés
bound_backpack: Lélekhez Kötött Tárolás
jetboots: Sugárhajtású Csizma
armored_jetboots: Páncélozott Sugárhajtású Csizmák
seismic_axe: Szeizmikus Fejsze
pickaxe_of_vein_mining: 'Ér Bányász Csákány '
bound_weapons: Lélekhez Kötött Fegyverek
bound_tools: Lélélekhez Kötött Eszközök
bound_armor: Lélekhez Kötött Páncél
juicer: Ízletes Italok
repaired_spawner: Spawnerek Javítása
enhanced_furnace: Továbbfejlesztett Kemence
more_enhanced_furnaces: Jobb Kemencék
high_tier_enhanced_furnaces: Magas Szintű Kemence
reinforced_furnace: Megerősített Kemence
carbonado_furnace: Karbonádó Szélű Kemence
electric_motor: Felmelegítés electric_motor: Felmelegítés
block_placer: Blokk Lehelyező
scroll_of_dimensional_teleposition: Megfordítva a dolgokat
special_bows: Robin Hood
tome_of_knowledge_sharing: Megosztás a barátokkal
flask_of_knowledge: XP Tároló
hardened_glass: Robbanások Ellen
golden_apple_juice: Arany Főzet
cooler: Hordozható Italok
ancient_altar: Ősi Oltár
wither_proof_obsidian: Wither-Védett Obszidián
ancient_runes: Elemi Rúnák
special_runes: Lila Rúnák
infernal_bonemeal: Pokoli Csontliszt
rainbow_blocks: Szivárvány Blokkok
infused_hopper: Pokoli Tölcsér
wither_proof_glass: Wither-Védett Üveg
duct_tape: Szövetbetétes Ragasztószalag
plastic_sheet: Műanyag
android_memory_core: Memóriamag
oil: Olaj
fuel: Üzemanyag
hologram_projector: Hologramok
capacitors: 1. Szintű Kondenzátorok
high_tier_capacitors: 2. Szintű Kondenzátorok
solar_generators: Napenergia Erőmű
electric_furnaces: Erős Kemence
electric_ore_grinding: Zúzás és Őrlés electric_ore_grinding: Zúzás és Őrlés
electric_press: Elektromos Prés heated_pressure_chamber: Fűtött Nyomáskamra
electric_smeltery: Elektromos Olvasztó coal_generator: Széngenerátor
elemental_staff: Elemi Pálcák bio_reactor: Bioreaktor
auto_enchanting: Automatikus Fejlesztés és Fejlesztés Törlés
auto_anvil: Automatikus Üllő
multimeter: Teljesítménymérés
gps_setup: Alapvető GPS Beállítás
gps_emergency_transmitter: GPS Vészhelyzeti Útpont
programmable_androids: Programozható Androidok
android_interfaces: Android Csatlakozási Felületek
geo_scanner: GEO-Vizsgálatok
combustion_reactor: Égésreaktor
teleporter: Teleportáló Alapelemek
teleporter_activation_plates: Teleportáló Aktiválás
better_solar_generators: Továbbfejlesztett Napelemes Generátorok
better_gps_transmitters: Továbbfejlesztett Transzmitterek
elevator: Liftek elevator: Liftek
elytra: Kitinszárnyak energized_solar_generator: Teljes-Munkaidős Napenergia
energized_gps_transmitter: Legfelső Szintű Transzmitter
energy_regulator: Energiahálózatok 101
butcher_androids: Hentes Androidok
organic_food: Bioélelmiszerek
auto_breeder: Automatizált Etetés
advanced_android: Speciális Androidok
advanced_butcher_android: Fejlett Androidok - Hentes
advanced_fisherman_android: Fejlett Androidok - Halász
animal_growth_accelerator: Az állatok Növekedésének Manipulálása
xp_collector: XP Gyűjtő
organic_fertilizer: Organikus Trágya
crop_growth_accelerator: Növény Növekedés Gyorsító
better_crop_growth_accelerator: Továbbfejlesztett Növény Növekedés Gyorsító
reactor_essentials: Reaktor Alapjai
nuclear_reactor: Atomerőmű
freezer: Fagyasztó Úr
cargo_basics: Szállítmány Alapjai
cargo_nodes: Szállítmány Beállítása
electric_ingot_machines: Elektromos Öntvénygyártás
high_tier_electric_ingot_machines: Szupergyors Öntvénygyártás
automated_crafting_chamber: Automatizált Barkácsolás
better_food_fabricator: Továbbfejlesztett Élelmiszergyártás
reactor_access_port: Reaktor Kölcsönhatás
fluid_pump: Folyadék Szivattyú
better_freezer: Továbbfejlesztett Fagyasztó
boosted_uranium: Soha Véget Nem Érő Kör
trash_can: Szemetes
advanced_output_node: Speciális Kimeneti Csomópont
carbon_press: Szénprés
electric_smeltery: Elektromos Olvasztó
better_electric_furnace: Továbbfejlesztett Elektromos Kemence
better_carbon_press: Továbbfejlesztett Szénprés
empowered_android: Felhatalmazott Androidok empowered_android: Felhatalmazott Androidok
empowered_butcher_android: Felhatalmazott Androidok - Hentes empowered_butcher_android: Felhatalmazott Androidok - Hentes
empowered_fisherman_android: Felhatalmazott Androidok - Halász empowered_fisherman_android: Felhatalmazott Androidok - Halász
ender_armor: Ender Páncél
ender_backpack: Ender Hátizsák
ender_talismans: Ender Talizmánok
energized_gps_transmitter: Legfelső Szintű Transzmitter
energized_solar_generator: Teljes-Munkaidős Napenergia
energy_regulator: Energiahálózatok 101
enhanced_furnace: Továbbfejlesztett Kemence
essence_of_afterlife: Szellemidézés
explosive_tools: Robbanóeszközök
farmer_shoes: Farmer Cipők
fire_staff: Tűz Pálca
fire_talisman: A Tűzoltó Talizmánja
first_aid: Elsősegély
flask_of_knowledge: XP Tároló
fluid_pump: Folyadék Szivattyú
fortune_cookie: Szerencsesüti
freezer: Fagyasztó Úr
fuel: Üzemanyag
geo_miner: GEO-Bányász
geo_scanner: GEO-Vizsgálatok
gilded_backpack: Aranyozott Hátizsák
gilded_iron: Fényes Vas
gilded_iron_armor: Aranyozott Vaspáncél
glowstone_armor: Izzókő Páncél
gold_armor: Fényes Páncél
gold_carats: Tiszta Arany
golden_apple_juice: Arany Főzet
gold_pan: Aranymosó
gps_emergency_transmitter: GPS Vészhelyzeti Útpont
gps_setup: Alapvető GPS Beállítás
grappling_hook: Vasmacska
grind_stone: Köszörűkő
hardened_glass: Robbanások Ellen
hazmat_suit: Vegyvédelmi Ruha
heated_pressure_chamber: Fűtött Nyomáskamra
hercules_pickaxe: Herkules Csákány
high_tier_capacitors: 2. Szintű Kondenzátorok
high_tier_carbon_press: Végleges Szénprés high_tier_carbon_press: Végleges Szénprés
high_tier_electric_ingot_machines: Szupergyors Öntvénygyártás wither_assembler: Automatizált Wither Ölő
high_tier_enhanced_furnaces: Magas Szintű Kemence better_heated_pressure_chamber: Továbbfejlesztett Fűtött Nyomású Kamra
hologram_projector: Hologramok elytra: Kitinszárnyak
hunter_talisman: A Vadász Talizmánja special_elytras: Speciális Kitinszárnyak
infernal_bonemeal: Pokoli Csontliszt electric_crucible: Elektromos Olvasztótégely
infused_hopper: Pokoli Tölcsér better_electric_crucibles: Forró Olvasztótégelyek
infused_magnet: Infúziós Mágnesek advanced_electric_smeltery: Fejlett Elektromos Olvasztómű
jetboots: Sugárhajtású Csizma advanced_farmer_android: Fejlett Androidok - Farmer
jetpacks: Jetpackek
juicer: Ízletes Italok
kelp_cookie: Ízletes Moszat
knight_talisman: A Lovag Talizmánja
lava_crystal: Tüzes Helyzet
lava_generator: Lávagenerátor lava_generator: Lávagenerátor
lava_talisman: A Láva Járó Talizmánja
lightning_rune: Villám Rúna
lumber_axe: Fadöntő Fejsze
lumps: Rögök és Varázslat
magical_book_cover: Varázslatos Könyvkötés
magic_eye_of_ender: Varázslatos Ender Szeme
magician_talisman: A Bűvész Talizmánja
magic_sugar: Varázscukor
magic_workbench: Varázslatos Barkácsasztal
magnesium_generator: Energia Magnéziumból
magnet: Mágneses Fémek
meat_jerky: Pácolt Hús
miner_talisman: A Bányász Talizmánja
misc_power_items: Fontos energiával kapcsolatos tárgyak
monster_jerky: Pácolt Szörnyhús
more_enhanced_furnaces: Jobb Kemencék
multimeter: Teljesítménymérés
multitools: Többfunkciós Eszközök
nether_gold_pan: Nether Aranymosó
nether_ice: Nether Jéghűtő nether_ice: Nether Jéghűtő
nether_star_reactor: Nethercsillag Reaktor nether_star_reactor: Nethercsillag Reaktor
nickel_and_cobalt: Még több Érc blistering_ingots: Hólyagos Radioaktivitás
night_vision_googles: Éjjellátó Szemüvegek automatic_ignition_chamber: Automatikus Gyújtókamra
nuclear_reactor: Atomerőmű
oil: Olaj
ore_crusher: Érc Duplázás
ore_washer: Ércmosó
organic_fertilizer: Organikus Trágya
organic_food: Bioélelmiszerek
output_chest: Alapvető Gépek Kimeneti Láda output_chest: Alapvető Gépek Kimeneti Láda
parachute: Ejtőernyő copper_wire: Hígított Vezetőképesség
pickaxe_of_containment: Csomagtartó Csákány
pickaxe_of_the_seeker: A Kutatók Csákánya
pickaxe_of_vein_mining: 'Ér Bányász Csákány '
plastic_sheet: Műanyag
portable_crafter: Hordozható Barkácsoló
portable_dustbin: Hordozható Kuka
pressure_chamber: Nyomáskamra
programmable_androids: Programozható Androidok
radiant_backpack: Sugárzó Hátizsák radiant_backpack: Sugárzó Hátizsák
rainbow_blocks: Szivárvány Blokkok auto_drier: Egy Száraz Nap
reactor_access_port: Reaktor Kölcsönhatás diet_cookie: Diétás Süti
reactor_essentials: Reaktor Alapjai
redstone_alloy: Redstone Ötvözet
reinforced_alloy: Megerősített Ötvözet
reinforced_armor: Megerősített Páncél
reinforced_furnace: Megerősített Kemence
repaired_spawner: Spawnerek Javítása
scroll_of_dimensional_teleposition: Megfordítva a dolgokat
seismic_axe: Szeizmikus Fejsze
silicon: Szilícium-völgy
slime_armor: Nyálka Páncél
slimefun_metals: Új Fémek
slime_steel_armor: Nyálkás Acél Páncél
smelters_pickaxe: Olvasztó Csákány
smeltery: Kohó
solar_generators: Napenergia Erőmű
solar_panel_and_helmet: Napenergia
soulbound_rune: Lélekhez Kötött Rúna
special_bows: Robin Hood
special_elytras: Speciális Kitinszárnyak
special_runes: Lila Rúnák
steel: Acélkor
steel_plate: Acéllemez
steel_thruster: Acélhajtómű
storm_staff: Vihar Pálca storm_staff: Vihar Pálca
sword_of_beheading: Lefejezés Kardja soulbound_rune: Lélekhez Kötött Rúna
synthetic_diamond: Szintetikus Gyémántok geo_miner: GEO-Bányász
synthetic_emerald: Hamis Drágakő lightning_rune: Villám Rúna
synthetic_sapphire: Szintetikus Zafírok
table_saw: Asztali Fűrész
teleporter: Teleportáló Alapelemek
teleporter_activation_plates: Teleportáló Aktiválás
tome_of_knowledge_sharing: Megosztás a barátokkal
totem_of_undying: Életmentés Toteme totem_of_undying: Életmentés Toteme
trash_can: Szemetes charging_bench: Töltőpad
traveller_talisman: Az Utazó Talizmánja nether_gold_pan: Nether Aranymosó
uranium: Radioaktív electric_press: Elektromos Prés
walking_sticks: Sétapálcák magnesium_generator: Energia Magnéziumból
warrior_talisman: A Harcos Talizmánja kelp_cookie: Ízletes Moszat
water_staff: Víz Pálca
water_talisman: A Vízlélegzés Talizmánja
whirlwind_talisman: A Forgószél Talizmánja
wind_staff: Szél Pálca
wither_assembler: Automatizált Wither Ölő
wither_proof_glass: Wither-Védett Üveg
wither_proof_obsidian: Wither-Védett Obszidián
wizard_talisman: A Varázsló Talizmánja
woven_backpack: Szőtt Hátizsák
xp_collector: XP Gyűjtő
makeshift_smeltery: Improvizált Olvasztó makeshift_smeltery: Improvizált Olvasztó
tree_growth_accelerator: Gyorsabb Fák tree_growth_accelerator: Gyorsabb Fák
industrial_miner: Ipari Bányászat
advanced_industrial_miner: Jobb Bányászat
magical_zombie_pills: Zombi Átváltoztató
auto_brewer: Ipari Sörgyár

View File

@ -1,7 +1,7 @@
--- ---
tooltips: tooltips:
results: GEO-Vizsgálat Eredmények results: GEO-Vizsgálat Eredmények
chunk: Vizsgált Chunkok chunk: Vizsgált Chunk
world: Világ world: Világ
unit: Egység unit: Egység
units: Egységek units: Egységek