Skip to content

Commit

Permalink
Add data.sync option that loads the data on the main thread
Browse files Browse the repository at this point in the history
(cherry picked from commit c7d2a94)
  • Loading branch information
WolfyScript committed Jul 2, 2024
1 parent e667fa7 commit bca3359
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class DataSettings {
private static final String PRINT_STACKTRACE = "print_stacktrace";
private static final String BUKKIT_VERSION = "bukkit_version";
private static final String CONFIG_VERSION = "version";
private static final String SYNC = "sync";

private final ConfigurationSection section;

Expand All @@ -56,6 +57,10 @@ private Pair<Long, TimeUnit> timeout(ConfigurationSection section, String key) {
Objects.requireNonNullElse(TimeUnit.valueOf(section.getString(key + ".unit")), TimeUnit.SECONDS));
}

public boolean sync() {
return section.getBoolean(SYNC, false);
}

public boolean printPending() {
return section.getBoolean(PRINT_PENDING);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import me.wolfyscript.utilities.util.NamespacedKey;
import me.wolfyscript.utilities.util.Pair;
import org.apache.commons.lang3.time.StopWatch;
import org.bukkit.Bukkit;

import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -146,6 +147,9 @@ public void load() {
api.getConsole().info("- - - - [Local Storage] - - - -");
int processors = Math.min(Runtime.getRuntime().availableProcessors(), dataSettings.maxProcessors());
customCrafting.getLogger().info(PREFIX + "Using " + processors + " threads");
if (dataSettings.sync()) {
customCrafting.getLogger().info(PREFIX + "Loading data synchronously");
}
executor = Executors.newWorkStealingPool(processors);
api.getConsole().info(PREFIX + "Looking through data folder...");
String[] dirs = DATA_FOLDER.list();
Expand Down Expand Up @@ -416,7 +420,7 @@ private void checkDependenciesAndRegister(CustomRecipe<?> recipe) {
/**
* Used to load data & cache the loaded, skipped errors & already existing keys.
*/
private abstract static class DataLoader {
private abstract class DataLoader {

protected final String[] dirs;

Expand All @@ -426,6 +430,28 @@ private DataLoader(String[] dirs) {

protected abstract void load();

protected void executeTask(Runnable runnable) {
if (dataSettings.sync()) {
if (Bukkit.isPrimaryThread()) {
// This option will cause the task to run on the main thread! Required for plugins like MMOItems
runnable.run();
} else {
// The LocalStorageLoader was not called from the main thread.
// Not sure what to do in this case... maybe a hacky Future thingy will work
try {
Bukkit.getScheduler().callSyncMethod(customCrafting, () -> {
runnable.run();
return true;
}).get(dataSettings.timeoutLoading().getKey(), dataSettings.timeoutLoading().getValue());
} catch (InterruptedException | ExecutionException | TimeoutException e) {
customCrafting.getLogger().log(Level.SEVERE, "Error while loading recipe ", e);
}
}
} else {
executor.execute(runnable);
}
}

}

private class NewDataLoader extends DataLoader {
Expand All @@ -448,7 +474,7 @@ private void loadRecipesInNamespace(String namespace) {
if (isValidFile(file.toFile())) return FileVisitResult.CONTINUE;
final var namespacedKey = keyFromFile(namespace, relative);
if (isReplaceData() || !customCrafting.getRegistries().getRecipes().has(namespacedKey)) {
executor.execute(() -> {
executeTask(() -> {
try {
var injectableValues = new InjectableValues.Std();
injectableValues.addValue("key", namespacedKey);
Expand Down Expand Up @@ -533,7 +559,7 @@ protected void loadOldOrLegacyRecipeFiles(RecipeLoader<?> loader, List<File> fil
if (isValidFile(file)) continue;
var namespacedKey = new NamespacedKey(customCrafting, namespace + "/" + name.substring(0, name.lastIndexOf(".")));
if (!customCrafting.getRegistries().getRecipes().has(namespacedKey)) {
executor.execute(() -> {
executeTask(() -> {
try {
CustomRecipe<?> recipe = loader.getInstance(namespacedKey, objectMapper.readTree(file));
checkDependenciesAndRegister(recipe);
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ data:
# Specifies the maximum number of processors to use for loading the data
# Uses either all available processors, or the specified count, whichever is smaller
max_processors: 64
# When set true, uses the sync scheduler to load the items & recipes.
# Data is then loaded sequentially and not parallel across multiple cores (ignores 'max_processors')
sync: false
# Specifies if it should print details about why the recipes are pending.
# Recipes are mostly pending because of dependencies, and are validated once a dependency is done loading its data.
# Usually not required as pending recipes not validated are marked as 'invalid' after a given timeout (see 'data.timeout.pending').
Expand Down

0 comments on commit bca3359

Please sign in to comment.