diff --git a/.gitignore b/.gitignore index ab2a28212..b1c99d269 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,7 @@ gradle-app.setting # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* +*.hprof ### JetBrains template # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider diff --git a/README.md b/README.md index 42b12fcbc..45629f0eb 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,25 @@ # Terra -Terra is a data-driven world generator based on [Gaea](https://github.com/PolyhedralDev/Gaea). Find out more on our -[Spigot page](https://www.spigotmc.org/resources/85151/)! + +Terra is an incredibly powerful free & open-source data-driven, platform-agnostic world generator. It allows you to create a world exactly +to your specifications, with no knowledge of Java required. + +## Downloads: + +* Paper+ servers (Paper, Tuinity, Purpur, etc): [SpigotMC](https://www.spigotmc.org/resources/85151/) +* Fabric: [Modrinth](https://modrinth.com/mod/terra) / [CurseForge](https://www.curseforge.com/minecraft/mc-mods/terra-world-generator) ## Building and running Terra -To build, simply run `./gradlew build` on Linux/MacOS, or `gradlew.bat build` on Windows. -This will produce a jar in `build/libs` called `Terra-[CURRENT VERSION].jar`. -You can put this right into your plugins dir, along with the correct Gaea version. + +To build, simply run `./gradlew build` (`gradlew.bat build` on Windows). This will produce a jar in `build/libs` +called `Terra-[CURRENT VERSION].jar`. You can put this right into your plugins dir, along with the correct Gaea version. If you would like to test it with a default server config, just run `./gradlew setupServer` or -`./gradlew.bat setupServer` to set up the server, then `./gradlew testWithPaper` or `gradlew.bat testWithPaper` to run -the server. If you want a clean installation of the server, re-run the `setupServer` task. -This will download a default server config from [here](https://github.com/PolyhedralDev/WorldGenTestServer) +`./gradlew.bat setupServer` to set up the server, then `./gradlew testWithPaper` or `gradlew.bat testWithPaper` to run the server. If you +want a clean installation of the server, re-run the `setupServer` task. This will download a default server config +from [here](https://github.com/PolyhedralDev/WorldGenTestServer) and install the server in the `target/server` directory, along with all the needed plugins. - -**Note: You will need to adjust the `NAME` variable `bukkit.yml` of the test server if you are not using the default -Terra config.** + +**Note: You will need to adjust the `NAME` variable `bukkit.yml` of the test server if you are not using the default Terra config.** ## Contributing Contributions are welcome! If you want to see a feature in Terra, please, open an issue, or implement it yourself and diff --git a/build.gradle.kts b/build.gradle.kts index cfe89a530..7b8933395 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,6 @@ import com.dfsek.terra.getGitHash -val versionObj = Version("4", "3", "0", true) +val versionObj = Version("5", "0", "0", true) allprojects { version = versionObj diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt index ae2f81b9c..a6619cc1f 100644 --- a/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt +++ b/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt @@ -6,7 +6,9 @@ import org.gradle.api.plugins.JavaPluginConvention import org.gradle.api.tasks.compile.JavaCompile import org.gradle.api.tasks.javadoc.Javadoc import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.filter import org.gradle.kotlin.dsl.withType +import org.gradle.language.jvm.tasks.ProcessResources fun Project.configureCompilation() { configure { @@ -21,6 +23,15 @@ fun Project.configureCompilation() { } } + tasks.withType { + include("**/*.*") + filter( + "tokens" to mapOf( + "VERSION" to project.version.toString() + ) + ) + } + tasks.withType { options.encoding = "UTF-8" } diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 38d982bca..5938324de 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -18,10 +18,13 @@ dependencies { "shadedApi"("net.jafama:jafama:2.3.2") "shadedApi"("org.yaml:snakeyaml:1.27") "shadedApi"("org.ow2.asm:asm:9.0") + "shadedApi"("commons-io:commons-io:2.6") "compileOnly"("com.googlecode.json-simple:json-simple:1.1") - "shadedApi"("com.google.guava:guava:30.0-jre") + "compileOnly"("com.google.guava:guava:30.0-jre") + + "testImplementation"("com.google.guava:guava:30.0-jre") } publishing { diff --git a/common/src/main/java/com/dfsek/terra/addon/AddonClassLoader.java b/common/src/main/java/com/dfsek/terra/addon/AddonClassLoader.java new file mode 100644 index 000000000..6f09a5307 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/addon/AddonClassLoader.java @@ -0,0 +1,61 @@ +package com.dfsek.terra.addon; + +import com.dfsek.terra.api.addons.TerraAddon; +import com.dfsek.terra.api.addons.annotations.Addon; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +public class AddonClassLoader extends URLClassLoader { + static { + ClassLoader.registerAsParallelCapable(); + } + + public AddonClassLoader(URL[] urls, ClassLoader parent) { + super(urls, parent); + } + + public AddonClassLoader(URL[] urls) { + super(urls); + } + + @SuppressWarnings("unchecked") + public static Set> fetchAddonClasses(File file) throws IOException { + JarFile jarFile = new JarFile(file); + Enumeration entries = jarFile.entries(); + + AddonClassLoader loader = new AddonClassLoader(new URL[] {file.toURI().toURL()}, AddonClassLoader.class.getClassLoader()); + + Set> set = new HashSet<>(); + while(entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + + if(entry.isDirectory() || !entry.getName().endsWith(".class")) continue; + String className = entry.getName().substring(0, entry.getName().length() - 6).replace('/', '.'); + + try { + Class clazz = loader.loadClass(className); + + Addon addon = clazz.getAnnotation(Addon.class); + + if(addon == null) continue; + + if(!TerraAddon.class.isAssignableFrom(clazz)) + throw new IllegalArgumentException("Addon class \"" + clazz + "\" must extend TerraAddon."); + + set.add((Class) clazz); + } catch(ClassNotFoundException e) { + throw new IllegalStateException(e); // this should literally never happen, if it does something is very wrong + } + } + + return set; + } +} diff --git a/common/src/main/java/com/dfsek/terra/addon/AddonPool.java b/common/src/main/java/com/dfsek/terra/addon/AddonPool.java new file mode 100644 index 000000000..5636aa06b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/addon/AddonPool.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.addon; + +import com.dfsek.terra.addon.exception.AddonLoadException; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class AddonPool { + private final Map pool = new HashMap<>(); + + public void add(PreLoadAddon addon) throws AddonLoadException { + if(pool.containsKey(addon.getId())) { + String message = "Duplicate addon ID: " + + addon.getId() + "; original ID from file: " + + pool.get(addon.getId()).getFile().getAbsolutePath() + + ", class: " + + pool.get(addon.getId()).getAddonClass().getCanonicalName() + + "Duplicate ID from file: " + + addon.getFile().getAbsolutePath() + + ", class: " + + addon.getAddonClass().getCanonicalName(); + throw new AddonLoadException(message); + } + pool.put(addon.getId(), addon); + } + + public PreLoadAddon get(String id) { + return pool.get(id); + } + + public void buildAll() throws AddonLoadException { + for(PreLoadAddon value : pool.values()) { + value.rebuildDependencies(this, value, true); + } + } + + public Set getAddons() { + return new HashSet<>(pool.values()); + } +} diff --git a/common/src/main/java/com/dfsek/terra/addon/PreLoadAddon.java b/common/src/main/java/com/dfsek/terra/addon/PreLoadAddon.java new file mode 100644 index 000000000..7b21ecb40 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/addon/PreLoadAddon.java @@ -0,0 +1,58 @@ +package com.dfsek.terra.addon; + +import com.dfsek.terra.addon.exception.AddonLoadException; +import com.dfsek.terra.addon.exception.CircularDependencyException; +import com.dfsek.terra.addon.exception.DependencyMissingException; +import com.dfsek.terra.api.addons.TerraAddon; +import com.dfsek.terra.api.addons.annotations.Addon; +import com.dfsek.terra.api.addons.annotations.Depends; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class PreLoadAddon { + private final List depends = new ArrayList<>(); + private final Class addonClass; + private final String id; + private final String[] dependencies; + private final File file; + + public PreLoadAddon(Class addonClass, File file) { + this.addonClass = addonClass; + this.id = addonClass.getAnnotation(Addon.class).value(); + this.file = file; + Depends depends = addonClass.getAnnotation(Depends.class); + this.dependencies = depends == null ? new String[] {} : depends.value(); + } + + public List getDepends() { + return depends; + } + + public void rebuildDependencies(AddonPool pool, PreLoadAddon origin, boolean levelG1) throws AddonLoadException { + if(this.equals(origin) && !levelG1) + throw new CircularDependencyException("Detected circular dependency in addon \"" + id + "\", dependencies: " + Arrays.toString(dependencies)); + + for(String dependency : dependencies) { + PreLoadAddon preLoadAddon = pool.get(dependency); + if(preLoadAddon == null) + throw new DependencyMissingException("Dependency " + dependency + " was not found. Please install " + dependency + " to use " + id + "."); + depends.add(preLoadAddon); + preLoadAddon.rebuildDependencies(pool, origin, false); + } + } + + public String getId() { + return id; + } + + public Class getAddonClass() { + return addonClass; + } + + public File getFile() { + return file; + } +} diff --git a/common/src/main/java/com/dfsek/terra/addon/exception/AddonLoadException.java b/common/src/main/java/com/dfsek/terra/addon/exception/AddonLoadException.java new file mode 100644 index 000000000..e0ff046d5 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/addon/exception/AddonLoadException.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.addon.exception; + +public class AddonLoadException extends Exception { + private static final long serialVersionUID = -4949084729296580176L; + + public AddonLoadException(String message) { + super(message); + } + + public AddonLoadException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/addon/exception/CircularDependencyException.java b/common/src/main/java/com/dfsek/terra/addon/exception/CircularDependencyException.java new file mode 100644 index 000000000..88513f6b1 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/addon/exception/CircularDependencyException.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.addon.exception; + +public class CircularDependencyException extends AddonLoadException { + private static final long serialVersionUID = 7398510879124125121L; + + public CircularDependencyException(String message) { + super(message); + } + + public CircularDependencyException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/addon/exception/DependencyMissingException.java b/common/src/main/java/com/dfsek/terra/addon/exception/DependencyMissingException.java new file mode 100644 index 000000000..fec11d10f --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/addon/exception/DependencyMissingException.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.addon.exception; + +public class DependencyMissingException extends AddonLoadException { + private static final long serialVersionUID = -8419489102208521583L; + + public DependencyMissingException(String message) { + super(message); + } + + public DependencyMissingException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/TerraPlugin.java b/common/src/main/java/com/dfsek/terra/api/TerraPlugin.java new file mode 100644 index 000000000..fb9f87613 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/TerraPlugin.java @@ -0,0 +1,67 @@ +package com.dfsek.terra.api; + +import com.dfsek.terra.api.addons.TerraAddon; +import com.dfsek.terra.api.event.EventManager; +import com.dfsek.terra.api.platform.handle.ItemHandle; +import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.registry.LockedRegistry; +import com.dfsek.terra.api.util.logging.DebugLogger; +import com.dfsek.terra.api.util.logging.Logger; +import com.dfsek.terra.config.PluginConfig; +import com.dfsek.terra.config.lang.Language; +import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.world.TerraWorld; + +import java.io.File; + +/** + * Represents a Terra mod/plugin instance. + */ +public interface TerraPlugin extends LoaderRegistrar { + WorldHandle getWorldHandle(); + + TerraWorld getWorld(World world); + + Logger logger(); + + PluginConfig getTerraConfig(); + + File getDataFolder(); + + boolean isDebug(); + + Language getLanguage(); + + CheckedRegistry getConfigRegistry(); + + LockedRegistry getAddons(); + + boolean reload(); + + ItemHandle getItemHandle(); + + void saveDefaultConfig(); + + String platformName(); + + DebugLogger getDebugLogger(); + + EventManager getEventManager(); + + default String getVersion() { + return "@VERSION@"; + } + + /** + * Runs a task that may or may not be thread safe, depending on platform. + *

+ * Allows platforms to define what code is safe to be run asynchronously. + * + * @param task Task to be run. + */ + default void runPossiblyUnsafeTask(Runnable task) { + task.run(); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/addons/TerraAddon.java b/common/src/main/java/com/dfsek/terra/api/addons/TerraAddon.java new file mode 100644 index 000000000..c202f9e39 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/addons/TerraAddon.java @@ -0,0 +1,49 @@ +package com.dfsek.terra.api.addons; + + +import com.dfsek.terra.api.addons.annotations.Addon; +import com.dfsek.terra.api.addons.annotations.Author; +import com.dfsek.terra.api.addons.annotations.Version; +import org.jetbrains.annotations.NotNull; + +/** + * Represents an entry point for an addon. Implementations must be annotated with {@link Addon}. + */ +public abstract class TerraAddon { + /** + * Gets the version of this addon. + * + * @return Addon version. + */ + public final @NotNull String getVersion() { + Version version = getClass().getAnnotation(Version.class); + return version == null ? "0.1.0" : version.value(); + } + + /** + * Gets the author of this addon. + * + * @return Addon author. + */ + public final @NotNull String getAuthor() { + Author author = getClass().getAnnotation(Author.class); + return author == null ? "Anon Y. Mous" : author.value(); + } + + /** + * Gets the name (ID) of this addon. + * + * @return Addon ID. + */ + public final @NotNull String getName() { + Addon addon = getClass().getAnnotation(Addon.class); + if(addon == null) + throw new IllegalStateException("Addon annotation not present"); // This should never happen; the presence of this annotation is checked by the addon loader. + return addon.value(); + } + + /** + * Invoked immediately after an addon is loaded. + */ + public abstract void initialize(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/addons/annotations/Addon.java b/common/src/main/java/com/dfsek/terra/api/addons/annotations/Addon.java new file mode 100644 index 000000000..cf36cf6cf --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/addons/annotations/Addon.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.addons.annotations; + +import org.jetbrains.annotations.NotNull; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Specifies that the annotated class is an entry point for a Terra addon. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Addon { + /** + * @return The ID of the addon. + */ + @NotNull String value(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/addons/annotations/Author.java b/common/src/main/java/com/dfsek/terra/api/addons/annotations/Author.java new file mode 100644 index 000000000..7a7c70873 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/addons/annotations/Author.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.addons.annotations; + +import org.jetbrains.annotations.NotNull; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Optional annotation that specifies the author of an addon. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface Author { + /** + * @return Name of the addon author. + */ + @NotNull String value(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/addons/annotations/Depends.java b/common/src/main/java/com/dfsek/terra/api/addons/annotations/Depends.java new file mode 100644 index 000000000..8634335be --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/addons/annotations/Depends.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.addons.annotations; + +import org.jetbrains.annotations.NotNull; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Optional annotation that specifies dependencies of an addon. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Depends { + /** + * @return All addons this addon is dependent upon. + */ + @NotNull String[] value(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/addons/annotations/Version.java b/common/src/main/java/com/dfsek/terra/api/addons/annotations/Version.java new file mode 100644 index 000000000..a2f8c2743 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/addons/annotations/Version.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.addons.annotations; + +import org.jetbrains.annotations.NotNull; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Optional annotation that specifies the version of an addon. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Version { + /** + * @return Version of the addon. + */ + @NotNull String value(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/CommandManager.java b/common/src/main/java/com/dfsek/terra/api/command/CommandManager.java new file mode 100644 index 000000000..a33d70921 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/CommandManager.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.api.command; + +import com.dfsek.terra.api.command.exception.CommandException; +import com.dfsek.terra.api.command.exception.MalformedCommandException; +import com.dfsek.terra.api.platform.CommandSender; + +import java.util.List; + +public interface CommandManager { + void execute(String command, CommandSender sender, List args) throws CommandException; + + void register(String name, Class clazz) throws MalformedCommandException; + + List tabComplete(String command, CommandSender sender, List args) throws CommandException; + + int getMaxArgumentDepth(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/CommandTemplate.java b/common/src/main/java/com/dfsek/terra/api/command/CommandTemplate.java new file mode 100644 index 000000000..836192b6b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/CommandTemplate.java @@ -0,0 +1,7 @@ +package com.dfsek.terra.api.command; + +import com.dfsek.terra.api.platform.CommandSender; + +public interface CommandTemplate { + void execute(CommandSender sender); +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/ExecutionState.java b/common/src/main/java/com/dfsek/terra/api/command/ExecutionState.java new file mode 100644 index 000000000..89216bd89 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/ExecutionState.java @@ -0,0 +1,38 @@ +package com.dfsek.terra.api.command; + +import com.dfsek.terra.api.platform.CommandSender; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public final class ExecutionState { + private final Set switches = new HashSet<>(); + private final Map args = new HashMap<>(); + private final CommandSender sender; + + protected ExecutionState(CommandSender sender) { + this.sender = sender; + } + + protected void addSwitch(String flag) { + switches.add(flag); + } + + protected void addArgument(String arg, String value) { + args.put(arg, value); + } + + public String getArgument(String argument) { + return args.get(argument); + } + + public boolean hasSwitch(String flag) { + return switches.contains(flag); + } + + public CommandSender getSender() { + return sender; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/TerraCommandManager.java b/common/src/main/java/com/dfsek/terra/api/command/TerraCommandManager.java new file mode 100644 index 000000000..d76c3a83f --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/TerraCommandManager.java @@ -0,0 +1,284 @@ +package com.dfsek.terra.api.command; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.annotation.Argument; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.Subcommand; +import com.dfsek.terra.api.command.annotation.Switch; +import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; +import com.dfsek.terra.api.command.annotation.inject.SwitchTarget; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.command.arg.ArgumentParser; +import com.dfsek.terra.api.command.exception.CommandException; +import com.dfsek.terra.api.command.exception.ExecutionException; +import com.dfsek.terra.api.command.exception.InvalidArgumentsException; +import com.dfsek.terra.api.command.exception.MalformedCommandException; +import com.dfsek.terra.api.command.exception.SwitchFormatException; +import com.dfsek.terra.api.command.tab.TabCompleter; +import com.dfsek.terra.api.injection.Injector; +import com.dfsek.terra.api.injection.exception.InjectionException; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.util.ReflectionUtil; +import com.dfsek.terra.world.TerraWorld; +import net.jafama.FastMath; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class TerraCommandManager implements CommandManager { + private final Map commands = new HashMap<>(); + private final Injector pluginInjector; + private final TerraPlugin main; + + public TerraCommandManager(TerraPlugin main) { + this.main = main; + this.pluginInjector = new Injector<>(main); + pluginInjector.addExplicitTarget(TerraPlugin.class); + } + + @Override + public void execute(String commandName, CommandSender sender, List argsIn) throws CommandException { + if(!commands.containsKey(commandName)) throw new InvalidArgumentsException("No such command \"" + commandName + "\""); + execute(commands.get(commandName), sender, new ArrayList<>(argsIn)); + } + + private void execute(CommandHolder commandHolder, CommandSender sender, List args) throws CommandException { + Class commandClass = commandHolder.clazz; + + if(commandClass.isAnnotationPresent(DebugCommand.class) && !main.isDebug()) { + sender.sendMessage("Command must be executed with debug mode enabled."); + return; + } + + if(commandClass.isAnnotationPresent(PlayerCommand.class) && !(sender instanceof Player)) { + sender.sendMessage("Command must be executed by player."); + return; + } + + if(commandClass.isAnnotationPresent(WorldCommand.class) && (!(sender instanceof Player) || !TerraWorld.isTerraWorld(((Player) sender).getWorld()))) { + sender.sendMessage("Command must be executed in a Terra world."); + return; + } + + List ogArgs = new ArrayList<>(args); + + ExecutionState state = new ExecutionState(sender); + + if(!commandClass.isAnnotationPresent(Command.class)) { + invoke(commandClass, state, commandHolder); + return; + } + + Command command = commandClass.getAnnotation(Command.class); + + if(command.arguments().length == 0 && command.subcommands().length == 0) { + if(args.isEmpty()) { + invoke(commandClass, state, commandHolder); + return; + } else throw new InvalidArgumentsException("Expected 0 arguments, found " + args.size()); + } + + if(!args.isEmpty() && commandHolder.subcommands.containsKey(args.get(0))) { + String c = args.get(0); + args.remove(0); + execute(commandHolder.subcommands.get(c), sender, args); + return; + } + + boolean req = true; + for(Argument argument : command.arguments()) { + if(!req && argument.required()) { + throw new MalformedCommandException("Required arguments must come first! Arguments: " + Arrays.toString(command.arguments())); + } + req = argument.required(); + + if(args.isEmpty()) { + if(req) throw new InvalidArgumentsException("Invalid arguments: " + ogArgs + ", usage: " + command.usage()); + break; + } + + String arg = args.get(0); + + if(arg.startsWith("-")) { // switches have started. + if(req) throw new InvalidArgumentsException("Switches must come after arguments."); + break; + } + + state.addArgument(argument.value(), args.remove(0)); + } + + while(!args.isEmpty()) { + String aSwitch = args.remove(0); + if(!aSwitch.startsWith("-")) throw new SwitchFormatException("Invalid switch \"" + aSwitch + "\""); + + String val = aSwitch.substring(1); // remove dash + + if(!commandHolder.switches.containsKey(val)) throw new SwitchFormatException("No such switch \"" + aSwitch + "\""); + + state.addSwitch(commandHolder.switches.get(val)); + } + + invoke(commandClass, state, commandHolder); + } + + private void invoke(Class clazz, ExecutionState state, CommandHolder holder) throws CommandException { + try { + CommandTemplate template = clazz.getConstructor().newInstance(); + + pluginInjector.inject(template); + + for(Field field : ReflectionUtil.getFields(clazz)) { + if(field.isAnnotationPresent(ArgumentTarget.class)) { + ArgumentTarget argumentTarget = field.getAnnotation(ArgumentTarget.class); + if(!holder.argumentMap.containsKey(argumentTarget.value())) { + throw new MalformedCommandException("Argument Target specifies nonexistent argument \"" + argumentTarget.value() + "\""); + } + + String argument = argumentTarget.value(); + + ArgumentParser argumentParser = holder.argumentMap.get(argumentTarget.value()).argumentParser().getConstructor().newInstance(); + + pluginInjector.inject(argumentParser); + + field.setAccessible(true); + String value = state.getArgument(argument); + + if(value == null) value = holder.argumentMap.get(argumentTarget.value()).defaultValue(); + + field.set(template, argumentParser.parse(state.getSender(), value)); + } + if(field.isAnnotationPresent(SwitchTarget.class)) { + SwitchTarget switchTarget = field.getAnnotation(SwitchTarget.class); + if(!holder.switches.containsValue(switchTarget.value())) { + System.out.println(holder.switches); + throw new MalformedCommandException("Switch Target specifies nonexistent switch \"" + switchTarget.value() + "\""); + } + + if(!(field.getType() == boolean.class)) { + throw new MalformedCommandException("Switch Target must be of type boolean."); + } + + field.setAccessible(true); + field.setBoolean(template, state.hasSwitch(switchTarget.value())); + } + } + + try { + template.execute(state.getSender()); + } catch(Throwable e) { + throw new ExecutionException("Failed to execute command: " + e.getMessage(), e); + } + } catch(InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | InjectionException e) { + throw new MalformedCommandException("Unable to reflectively instantiate command: ", e); + } + } + + @Override + public void register(String name, Class clazz) throws MalformedCommandException { + commands.put(name, new CommandHolder(clazz)); + } + + @Override + public List tabComplete(String command, CommandSender sender, List args) throws CommandException { + if(args.isEmpty()) return new ArrayList<>(commands.keySet()).stream().sorted(String::compareTo).collect(Collectors.toList()); + if(!commands.containsKey(command)) return Collections.emptyList(); + return tabComplete(commands.get(command), sender, new ArrayList<>(args)).stream().filter(s -> s.toLowerCase().startsWith(args.get(args.size() - 1).toLowerCase())).sorted(String::compareTo).collect(Collectors.toList()); + } + + @Override + public int getMaxArgumentDepth() { + int max = 0; + for(CommandHolder value : commands.values()) { + max = FastMath.max(getMaxArgumentDepth(value), max); + } + return max; + } + + private int getMaxArgumentDepth(CommandHolder holder) { + int max = 0; + max = FastMath.max(holder.arguments.size() + holder.switchList.size(), max); + for(CommandHolder value : holder.subcommands.values()) { + max = FastMath.max(max, getMaxArgumentDepth(value) + 1); + } + return max; + } + + private List tabComplete(CommandHolder holder, CommandSender sender, List args) throws CommandException { + if(args.isEmpty()) return Collections.emptyList(); + List completions = new ArrayList<>(); + + if(args.size() == 1) { + completions.addAll(holder.subcommands.keySet()); + } + + if(holder.subcommands.containsKey(args.get(0))) { + List newArgs = new ArrayList<>(args); + newArgs.remove(0); + completions.addAll(tabComplete(holder.subcommands.get(args.get(0)), sender, newArgs)); + } + try { + if(args.size() <= holder.arguments.size()) { + TabCompleter completer = holder.arguments.get(args.size() - 1).tabCompleter().getConstructor().newInstance(); + pluginInjector.inject(completer); + completions.addAll(completer.complete(sender)); + } + } catch(InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | InjectionException e) { + throw new MalformedCommandException("Unable to reflectively instantiate tab-completer: ", e); + } + return completions; + } + + /** + * Pre-processes command metadata. + */ + private static final class CommandHolder { + private final Class clazz; + private final Map subcommands = new HashMap<>(); + private final Map switches = new HashMap<>(); + private final List arguments; + private final List switchList; + private final Map argumentMap = new HashMap<>(); + + private CommandHolder(Class clazz) throws MalformedCommandException { + this.clazz = clazz; + if(clazz.isAnnotationPresent(Command.class)) { + Command command = clazz.getAnnotation(Command.class); + for(Subcommand subcommand : command.subcommands()) { + if(subcommands.containsKey(subcommand.value())) + throw new MalformedCommandException("Duplicate subcommand: " + subcommand); + CommandHolder holder = new CommandHolder(subcommand.clazz()); + subcommands.put(subcommand.value(), holder); + for(String alias : subcommand.aliases()) { + subcommands.put(alias, holder); + } + } + for(Switch aSwitch : command.switches()) { + if(switches.containsKey(aSwitch.value())) throw new MalformedCommandException("Duplicate switch: " + aSwitch); + switches.put(aSwitch.value(), aSwitch.value()); + for(String alias : aSwitch.aliases()) { + switches.put(alias, aSwitch.value()); + } + } + for(Argument argument : command.arguments()) { + if(argumentMap.containsKey(argument.value())) throw new MalformedCommandException("Duplicate argument: " + argument); + argumentMap.put(argument.value(), argument); + } + arguments = Arrays.asList(command.arguments()); + switchList = Arrays.asList(command.switches()); + } else { + arguments = Collections.emptyList(); + switchList = Collections.emptyList(); + } + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/Argument.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/Argument.java new file mode 100644 index 000000000..d0c91a965 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/annotation/Argument.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.api.command.annotation; + +import com.dfsek.terra.api.command.arg.ArgumentParser; +import com.dfsek.terra.api.command.arg.StringArgumentParser; +import com.dfsek.terra.api.command.tab.NothingCompleter; +import com.dfsek.terra.api.command.tab.TabCompleter; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.ANNOTATION_TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Argument { + String value(); + + boolean required() default true; + + Class tabCompleter() default NothingCompleter.class; + + Class> argumentParser() default StringArgumentParser.class; + + String defaultValue() default ""; +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/Command.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/Command.java new file mode 100644 index 000000000..fb5fd81ea --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/annotation/Command.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.api.command.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Command { + Argument[] arguments() default {}; + + Switch[] switches() default {}; + + Subcommand[] subcommands() default {}; + + String usage() default ""; +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/Subcommand.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/Subcommand.java new file mode 100644 index 000000000..7f729ba0a --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/annotation/Subcommand.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.api.command.annotation; + +import com.dfsek.terra.api.command.CommandTemplate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.ANNOTATION_TYPE) +public @interface Subcommand { + String value(); + + String[] aliases() default {}; + + Class clazz(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/Switch.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/Switch.java new file mode 100644 index 000000000..16ea3e21a --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/annotation/Switch.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.command.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.ANNOTATION_TYPE) +public @interface Switch { + String value(); + + String[] aliases() default {}; +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/inject/ArgumentTarget.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/inject/ArgumentTarget.java new file mode 100644 index 000000000..89dbc5245 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/annotation/inject/ArgumentTarget.java @@ -0,0 +1,12 @@ +package com.dfsek.terra.api.command.annotation.inject; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface ArgumentTarget { + String value(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/inject/SwitchTarget.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/inject/SwitchTarget.java new file mode 100644 index 000000000..67478373a --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/annotation/inject/SwitchTarget.java @@ -0,0 +1,12 @@ +package com.dfsek.terra.api.command.annotation.inject; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface SwitchTarget { + String value(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/type/DebugCommand.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/type/DebugCommand.java new file mode 100644 index 000000000..174710401 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/annotation/type/DebugCommand.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.command.annotation.type; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Command may only be executed with debug mode enabled. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface DebugCommand { +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/type/PlayerCommand.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/type/PlayerCommand.java new file mode 100644 index 000000000..fd7b1e320 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/annotation/type/PlayerCommand.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.command.annotation.type; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marks command as player-only + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface PlayerCommand { +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/type/WorldCommand.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/type/WorldCommand.java new file mode 100644 index 000000000..c51ee570b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/annotation/type/WorldCommand.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.command.annotation.type; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Command may only be executed in a Terra world. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface WorldCommand { +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/arg/ArgumentParser.java b/common/src/main/java/com/dfsek/terra/api/command/arg/ArgumentParser.java new file mode 100644 index 000000000..3fcc5aeef --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/arg/ArgumentParser.java @@ -0,0 +1,7 @@ +package com.dfsek.terra.api.command.arg; + +import com.dfsek.terra.api.platform.CommandSender; + +public interface ArgumentParser { + T parse(CommandSender sender, String arg); +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/arg/DoubleArgumentParser.java b/common/src/main/java/com/dfsek/terra/api/command/arg/DoubleArgumentParser.java new file mode 100644 index 000000000..3f229b444 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/arg/DoubleArgumentParser.java @@ -0,0 +1,10 @@ +package com.dfsek.terra.api.command.arg; + +import com.dfsek.terra.api.platform.CommandSender; + +public class DoubleArgumentParser implements ArgumentParser { + @Override + public Double parse(CommandSender sender, String arg) { + return arg == null ? null : Double.parseDouble(arg); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/arg/IntegerArgumentParser.java b/common/src/main/java/com/dfsek/terra/api/command/arg/IntegerArgumentParser.java new file mode 100644 index 000000000..24e3186ca --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/arg/IntegerArgumentParser.java @@ -0,0 +1,10 @@ +package com.dfsek.terra.api.command.arg; + +import com.dfsek.terra.api.platform.CommandSender; + +public class IntegerArgumentParser implements ArgumentParser { + @Override + public Integer parse(CommandSender sender, String arg) { + return arg == null ? null : Integer.parseInt(arg); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/arg/StringArgumentParser.java b/common/src/main/java/com/dfsek/terra/api/command/arg/StringArgumentParser.java new file mode 100644 index 000000000..736b335d0 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/arg/StringArgumentParser.java @@ -0,0 +1,10 @@ +package com.dfsek.terra.api.command.arg; + +import com.dfsek.terra.api.platform.CommandSender; + +public class StringArgumentParser implements ArgumentParser { + @Override + public String parse(CommandSender sender, String arg) { + return arg; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/exception/CommandException.java b/common/src/main/java/com/dfsek/terra/api/command/exception/CommandException.java new file mode 100644 index 000000000..3fd6537ef --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/exception/CommandException.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.api.command.exception; + +public abstract class CommandException extends Exception { + private static final long serialVersionUID = -2955328495045879822L; + + public CommandException(String message) { + super(message); + } + + public CommandException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/exception/ExecutionException.java b/common/src/main/java/com/dfsek/terra/api/command/exception/ExecutionException.java new file mode 100644 index 000000000..061bfc64b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/exception/ExecutionException.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.api.command.exception; + +public class ExecutionException extends CommandException { + private static final long serialVersionUID = -6345523475880607959L; + + public ExecutionException(String message) { + super(message); + } + + public ExecutionException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/exception/InvalidArgumentsException.java b/common/src/main/java/com/dfsek/terra/api/command/exception/InvalidArgumentsException.java new file mode 100644 index 000000000..5ad88d0b3 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/exception/InvalidArgumentsException.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.api.command.exception; + +public class InvalidArgumentsException extends CommandException { + private static final long serialVersionUID = 7563619667472569824L; + + public InvalidArgumentsException(String message) { + super(message); + } + + public InvalidArgumentsException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/exception/MalformedCommandException.java b/common/src/main/java/com/dfsek/terra/api/command/exception/MalformedCommandException.java new file mode 100644 index 000000000..c124a8b85 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/exception/MalformedCommandException.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.api.command.exception; + +/** + * Thrown when command is incorrectly defined. + */ +public class MalformedCommandException extends CommandException { + private static final long serialVersionUID = -5417760860407895496L; + + public MalformedCommandException(String message) { + super(message); + } + + public MalformedCommandException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/exception/SwitchFormatException.java b/common/src/main/java/com/dfsek/terra/api/command/exception/SwitchFormatException.java new file mode 100644 index 000000000..c7e545ae7 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/exception/SwitchFormatException.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.api.command.exception; + +public class SwitchFormatException extends CommandException { + private static final long serialVersionUID = -965858989317844628L; + + public SwitchFormatException(String message) { + super(message); + } + + public SwitchFormatException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/tab/NothingCompleter.java b/common/src/main/java/com/dfsek/terra/api/command/tab/NothingCompleter.java new file mode 100644 index 000000000..111125505 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/tab/NothingCompleter.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.api.command.tab; + +import com.dfsek.terra.api.platform.CommandSender; + +import java.util.Collections; +import java.util.List; + +public class NothingCompleter implements TabCompleter { + @Override + public List complete(CommandSender sender) { + return Collections.emptyList(); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/tab/TabCompleter.java b/common/src/main/java/com/dfsek/terra/api/command/tab/TabCompleter.java new file mode 100644 index 000000000..33f875234 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/tab/TabCompleter.java @@ -0,0 +1,9 @@ +package com.dfsek.terra.api.command.tab; + +import com.dfsek.terra.api.platform.CommandSender; + +import java.util.List; + +public interface TabCompleter { + List complete(CommandSender sender); +} diff --git a/common/src/main/java/com/dfsek/terra/api/core/TerraPlugin.java b/common/src/main/java/com/dfsek/terra/api/core/TerraPlugin.java deleted file mode 100644 index 7fee3132f..000000000 --- a/common/src/main/java/com/dfsek/terra/api/core/TerraPlugin.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.dfsek.terra.api.core; - -import com.dfsek.terra.api.LoaderRegistrar; -import com.dfsek.terra.api.core.event.EventManager; -import com.dfsek.terra.api.platform.handle.ItemHandle; -import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.config.PluginConfig; -import com.dfsek.terra.config.lang.Language; -import com.dfsek.terra.debug.DebugLogger; -import com.dfsek.terra.registry.ConfigRegistry; -import com.dfsek.terra.world.TerraWorld; - -import java.io.File; -import java.util.logging.Logger; - -public interface TerraPlugin extends LoaderRegistrar { - WorldHandle getWorldHandle(); - - boolean isEnabled(); - - TerraWorld getWorld(World world); - - Logger getLogger(); - - PluginConfig getTerraConfig(); - - File getDataFolder(); - - boolean isDebug(); - - Language getLanguage(); - - ConfigRegistry getRegistry(); - - void reload(); - - ItemHandle getItemHandle(); - - void saveDefaultConfig(); - - String platformName(); - - - DebugLogger getDebugLogger(); - - EventManager getEventManager(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/core/event/EventListener.java b/common/src/main/java/com/dfsek/terra/api/core/event/EventListener.java deleted file mode 100644 index 276097e7d..000000000 --- a/common/src/main/java/com/dfsek/terra/api/core/event/EventListener.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.dfsek.terra.api.core.event; - -public interface EventListener { -} diff --git a/common/src/main/java/com/dfsek/terra/api/core/event/EventManager.java b/common/src/main/java/com/dfsek/terra/api/core/event/EventManager.java deleted file mode 100644 index 9f3e7e993..000000000 --- a/common/src/main/java/com/dfsek/terra/api/core/event/EventManager.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.core.event; - -import com.dfsek.terra.api.core.event.events.Event; - -public interface EventManager { - /** - * Call an event, and return the execution status. - * @param event Event to pass to all registered EventListeners. - * @return False if the event is cancellable and has been cancelled, otherwise true. - */ - boolean callEvent(Event event); - - void registerListener(EventListener listener); -} diff --git a/common/src/main/java/com/dfsek/terra/api/core/event/events/Cancellable.java b/common/src/main/java/com/dfsek/terra/api/core/event/events/Cancellable.java deleted file mode 100644 index 0d8a548c0..000000000 --- a/common/src/main/java/com/dfsek/terra/api/core/event/events/Cancellable.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dfsek.terra.api.core.event.events; - -/** - * Events that implement this interface may be cancelled. - * - * Cancelling an event is assumed to stop the execution of whatever action triggered the event. - */ -public interface Cancellable extends Event { - boolean isCancelled(); - void setCancelled(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/core/event/events/Event.java b/common/src/main/java/com/dfsek/terra/api/core/event/events/Event.java deleted file mode 100644 index 62a6e07f2..000000000 --- a/common/src/main/java/com/dfsek/terra/api/core/event/events/Event.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.dfsek.terra.api.core.event.events; - -public interface Event { -} diff --git a/common/src/main/java/com/dfsek/terra/api/core/event/events/config/ConfigPackLoadEvent.java b/common/src/main/java/com/dfsek/terra/api/core/event/events/config/ConfigPackLoadEvent.java deleted file mode 100644 index a69eba172..000000000 --- a/common/src/main/java/com/dfsek/terra/api/core/event/events/config/ConfigPackLoadEvent.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.api.core.event.events.config; - -import com.dfsek.terra.api.core.event.events.Event; -import com.dfsek.terra.config.pack.ConfigPack; - -public abstract class ConfigPackLoadEvent implements Event { - private final ConfigPack pack; - - public ConfigPackLoadEvent(ConfigPack pack) { - this.pack = pack; - } - - public ConfigPack getPack() { - return pack; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/event/EventListener.java b/common/src/main/java/com/dfsek/terra/api/event/EventListener.java new file mode 100644 index 000000000..cde546369 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/event/EventListener.java @@ -0,0 +1,12 @@ +package com.dfsek.terra.api.event; + +import com.dfsek.terra.api.event.events.Event; + +/** + * Marker interface for a class that contains event listener methods. + * + * @see Event + * @see EventManager + */ +public interface EventListener { +} diff --git a/common/src/main/java/com/dfsek/terra/api/event/EventManager.java b/common/src/main/java/com/dfsek/terra/api/event/EventManager.java new file mode 100644 index 000000000..de6ba0e19 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/event/EventManager.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.api.event; + +import com.dfsek.terra.api.addons.TerraAddon; +import com.dfsek.terra.api.event.events.Event; + +/** + * Manages event registration and triggering. + */ +public interface EventManager { + /** + * Call an event, and return the execution status. + * + * @param event Event to pass to all registered EventListeners. + * @return False if the event is cancellable and has been cancelled, otherwise true. + */ + boolean callEvent(Event event); + + /** + * Register an {@link EventListener} under an {@link TerraAddon}. + * + * @param addon Addon to register listener for. + * @param listener Listener to register. + */ + void registerListener(TerraAddon addon, EventListener listener); +} diff --git a/common/src/main/java/com/dfsek/terra/api/core/event/TerraEventManager.java b/common/src/main/java/com/dfsek/terra/api/event/TerraEventManager.java similarity index 58% rename from common/src/main/java/com/dfsek/terra/api/core/event/TerraEventManager.java rename to common/src/main/java/com/dfsek/terra/api/event/TerraEventManager.java index 2bb14ebd6..493efa364 100644 --- a/common/src/main/java/com/dfsek/terra/api/core/event/TerraEventManager.java +++ b/common/src/main/java/com/dfsek/terra/api/event/TerraEventManager.java @@ -1,9 +1,12 @@ -package com.dfsek.terra.api.core.event; +package com.dfsek.terra.api.event; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.api.core.event.annotations.Priority; -import com.dfsek.terra.api.core.event.events.Cancellable; -import com.dfsek.terra.api.core.event.events.Event; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.addons.TerraAddon; +import com.dfsek.terra.api.event.annotations.Global; +import com.dfsek.terra.api.event.annotations.Priority; +import com.dfsek.terra.api.event.events.Cancellable; +import com.dfsek.terra.api.event.events.Event; +import com.dfsek.terra.api.event.events.PackEvent; import com.dfsek.terra.api.util.ReflectionUtil; import java.io.PrintWriter; @@ -29,19 +32,30 @@ public class TerraEventManager implements EventManager { public boolean callEvent(Event event) { listeners.getOrDefault(event.getClass(), Collections.emptyList()).forEach(listenerHolder -> { try { - listenerHolder.method.invoke(listenerHolder.listener, event); + if(event instanceof PackEvent && !listenerHolder.global) { + PackEvent packEvent = (PackEvent) event; + if(packEvent + .getPack() + .getTemplate() + .getAddons() + .contains(listenerHolder.addon)) { + listenerHolder.method.invoke(listenerHolder.listener, event); + } + } else { + listenerHolder.method.invoke(listenerHolder.listener, event); + } } catch(InvocationTargetException e) { StringWriter writer = new StringWriter(); e.getTargetException().printStackTrace(new PrintWriter(writer)); - main.getLogger().warning("Exception occurred during event handling:"); - main.getLogger().warning(writer.toString()); - main.getLogger().warning("Report this to the maintainers of " + listenerHolder.method.getName()); + main.logger().warning("Exception occurred during event handling:"); + main.logger().warning(writer.toString()); + main.logger().warning("Report this to the maintainers of " + listenerHolder.method.getName()); } catch(Exception e) { StringWriter writer = new StringWriter(); e.printStackTrace(new PrintWriter(writer)); - main.getLogger().warning("Exception occurred during event handling:"); - main.getLogger().warning(writer.toString()); - main.getLogger().warning("Report this to the maintainers of " + listenerHolder.method.getName()); + main.logger().warning("Exception occurred during event handling:"); + main.logger().warning(writer.toString()); + main.logger().warning("Report this to the maintainers of " + listenerHolder.method.getName()); } } ); @@ -51,7 +65,7 @@ public class TerraEventManager implements EventManager { @SuppressWarnings("unchecked") @Override - public void registerListener(EventListener listener) { + public void registerListener(TerraAddon addon, EventListener listener) { Class listenerClass = listener.getClass(); Method[] methods = ReflectionUtil.getMethods(listenerClass); @@ -68,7 +82,7 @@ public class TerraEventManager implements EventManager { List holders = listeners.computeIfAbsent((Class) eventParam, e -> new ArrayList<>()); - holders.add(new ListenerHolder(method, listener, priority)); + holders.add(new ListenerHolder(method, listener, priority, addon, method.getAnnotation(Global.class) != null)); holders.sort(Comparator.comparingInt(ListenerHolder::getPriority)); // Sort priorities. } @@ -78,11 +92,15 @@ public class TerraEventManager implements EventManager { private final Method method; private final EventListener listener; private final int priority; + private final TerraAddon addon; + private final boolean global; - private ListenerHolder(Method method, EventListener listener, int priority) { + private ListenerHolder(Method method, EventListener listener, int priority, TerraAddon addon, boolean global) { this.method = method; this.listener = listener; this.priority = priority; + this.addon = addon; + this.global = global; } public int getPriority() { diff --git a/common/src/main/java/com/dfsek/terra/api/event/annotations/Global.java b/common/src/main/java/com/dfsek/terra/api/event/annotations/Global.java new file mode 100644 index 000000000..d162c00d9 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/event/annotations/Global.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.api.event.annotations; + +import com.dfsek.terra.api.event.events.PackEvent; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Specifies that an event handler is to handle all {@link PackEvent}s, regardless of whether the pack + * depends on the addon's listener. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Global { +} diff --git a/common/src/main/java/com/dfsek/terra/api/core/event/annotations/Priority.java b/common/src/main/java/com/dfsek/terra/api/event/annotations/Priority.java similarity index 88% rename from common/src/main/java/com/dfsek/terra/api/core/event/annotations/Priority.java rename to common/src/main/java/com/dfsek/terra/api/event/annotations/Priority.java index 7ee84aecd..2d5b7c11f 100644 --- a/common/src/main/java/com/dfsek/terra/api/core/event/annotations/Priority.java +++ b/common/src/main/java/com/dfsek/terra/api/event/annotations/Priority.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.api.core.event.annotations; +package com.dfsek.terra.api.event.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -12,11 +12,11 @@ import java.lang.annotation.Target; @Target(ElementType.METHOD) public @interface Priority { /** - * Highest possible priority. Listeners with this priority will always be invoked first. + * Highest possible priority. Listeners with this priority will always be invoked last. */ int HIGHEST = Integer.MAX_VALUE; /** - * Lowest possible priority. Listeners with this priority will always be invoked last. + * Lowest possible priority. Listeners with this priority will always be invoked first. */ int LOWEST = Integer.MIN_VALUE; /** diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/Cancellable.java b/common/src/main/java/com/dfsek/terra/api/event/events/Cancellable.java new file mode 100644 index 000000000..ca7bccdf7 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/event/events/Cancellable.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.api.event.events; + +/** + * Events that implement this interface may be cancelled. + *

+ * Cancelling an event is assumed to stop the execution of whatever action triggered the event. + */ +public interface Cancellable extends Event { + /** + * Get the cancellation status of the event. + * + * @return Whether event is cancelled. + */ + boolean isCancelled(); + + /** + * Set the cancellation status of the event. + * + * @param cancelled Whether event is cancelled. + */ + void setCancelled(boolean cancelled); +} diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/Event.java b/common/src/main/java/com/dfsek/terra/api/event/events/Event.java new file mode 100644 index 000000000..67d12a029 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/event/events/Event.java @@ -0,0 +1,7 @@ +package com.dfsek.terra.api.event.events; + +/** + * An event that addons may listen to. + */ +public interface Event { +} diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/PackEvent.java b/common/src/main/java/com/dfsek/terra/api/event/events/PackEvent.java new file mode 100644 index 000000000..66f7b7d6c --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/event/events/PackEvent.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.event.events; + +import com.dfsek.terra.api.event.annotations.Global; +import com.dfsek.terra.config.pack.ConfigPack; + +/** + * An event with functionality directly linked to a {@link ConfigPack}. + *

+ * PackEvents are only invoked when the pack specifies the addon in its + * {@code addon} key (or when the listener is annotated {@link Global}). + */ +@SuppressWarnings("InterfaceMayBeAnnotatedFunctional") +public interface PackEvent extends Event { + /** + * Get the {@link ConfigPack} associated with this event. + * + * @return ConfigPack associated with the event. + */ + ConfigPack getPack(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackLoadEvent.java b/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackLoadEvent.java new file mode 100644 index 000000000..7aa7ab8a4 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackLoadEvent.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.event.events.config; + +import com.dfsek.terra.api.event.events.PackEvent; +import com.dfsek.terra.config.pack.ConfigPack; + +/** + * An event related to the loading process of config packs. + */ +public abstract class ConfigPackLoadEvent implements PackEvent { + private final ConfigPack pack; + + public ConfigPackLoadEvent(ConfigPack pack) { + this.pack = pack; + } + + @Override + public ConfigPack getPack() { + return pack; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/core/event/events/config/ConfigPackPostLoadEvent.java b/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPostLoadEvent.java similarity index 82% rename from common/src/main/java/com/dfsek/terra/api/core/event/events/config/ConfigPackPostLoadEvent.java rename to common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPostLoadEvent.java index 838f0e22a..138de647c 100644 --- a/common/src/main/java/com/dfsek/terra/api/core/event/events/config/ConfigPackPostLoadEvent.java +++ b/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPostLoadEvent.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.api.core.event.events.config; +package com.dfsek.terra.api.event.events.config; import com.dfsek.terra.config.pack.ConfigPack; diff --git a/common/src/main/java/com/dfsek/terra/api/core/event/events/config/ConfigPackPreLoadEvent.java b/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPreLoadEvent.java similarity index 86% rename from common/src/main/java/com/dfsek/terra/api/core/event/events/config/ConfigPackPreLoadEvent.java rename to common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPreLoadEvent.java index e2d72d17d..317603c9e 100644 --- a/common/src/main/java/com/dfsek/terra/api/core/event/events/config/ConfigPackPreLoadEvent.java +++ b/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPreLoadEvent.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.api.core.event.events.config; +package com.dfsek.terra.api.event.events.config; import com.dfsek.terra.config.pack.ConfigPack; diff --git a/common/src/main/java/com/dfsek/terra/api/core/event/events/world/TerraWorldLoadEvent.java b/common/src/main/java/com/dfsek/terra/api/event/events/world/TerraWorldLoadEvent.java similarity index 51% rename from common/src/main/java/com/dfsek/terra/api/core/event/events/world/TerraWorldLoadEvent.java rename to common/src/main/java/com/dfsek/terra/api/event/events/world/TerraWorldLoadEvent.java index e68d174c3..213786432 100644 --- a/common/src/main/java/com/dfsek/terra/api/core/event/events/world/TerraWorldLoadEvent.java +++ b/common/src/main/java/com/dfsek/terra/api/event/events/world/TerraWorldLoadEvent.java @@ -1,6 +1,9 @@ -package com.dfsek.terra.api.core.event.events.world; +package com.dfsek.terra.api.event.events.world; -import com.dfsek.terra.api.core.event.events.Event; +import com.dfsek.terra.api.event.events.Event; +import com.dfsek.terra.api.event.events.PackEvent; +import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.config.pack.WorldConfig; import com.dfsek.terra.world.TerraWorld; /** @@ -16,4 +19,8 @@ public class TerraWorldLoadEvent implements Event { public TerraWorld getWorld() { return world; } + + public WorldConfig getPack() { + return world.getConfig(); + } } diff --git a/common/src/main/java/com/dfsek/terra/api/injection/Injector.java b/common/src/main/java/com/dfsek/terra/api/injection/Injector.java new file mode 100644 index 000000000..c19a680fa --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/injection/Injector.java @@ -0,0 +1,78 @@ +package com.dfsek.terra.api.injection; + +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.injection.exception.InjectionException; +import com.dfsek.terra.api.util.ReflectionUtil; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.HashSet; +import java.util.Set; + +/** + * Dynamic dependency injector. + *

+ * Stores an object to inject, and injects it into objects passed to {@link #inject(Object)}. + * + * @param Type of object to inject. + */ +public class Injector { + private final T value; + private final Set> targets = new HashSet<>(); + + /** + * Instantiate an Injector with a value to inject + * + * @param value Value to inject + */ + public Injector(T value) { + this.value = value; + } + + /** + * Add an explicit class as a target. Useful for applications where subclasses may cause issues with DI. + * + * @param target Target class type. + */ + public void addExplicitTarget(Class target) { + targets.add(target); + } + + /** + * Inject the stored object into an object. + *

+ * Injects the stored object into any non-static, non-final fields + * annotated with {@link Inject}, + * with type matching the stored object or any explicit targets + * ({@link #addExplicitTarget(Class)}. + * + * @param object Object to inject into + * @throws InjectionException If: + *

    + *
  • Matching field annotated with {@link Inject} is final
  • + *
  • Matching field annotated with {@link Inject} is static
  • + *
  • A reflective access exception occurs
  • + *
+ */ + public void inject(Object object) throws InjectionException { + for(Field field : ReflectionUtil.getFields(object.getClass())) { + Inject inject = field.getAnnotation(Inject.class); + if(inject == null) continue; + if(value.getClass().equals(field.getType()) || targets.contains(field.getType())) { + int mod = field.getModifiers(); + if(Modifier.isFinal(mod)) { + throw new InjectionException("Attempted to inject final field: " + field); + } + if(Modifier.isStatic(mod)) { + throw new InjectionException("Attempted to inject static field: " + field); + } + field.setAccessible(true); + try { + field.set(object, value); + } catch(IllegalAccessException e) { + throw new InjectionException("Failed to inject field: " + field, e); + } + } + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/injection/annotations/Inject.java b/common/src/main/java/com/dfsek/terra/api/injection/annotations/Inject.java new file mode 100644 index 000000000..b73f05d42 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/injection/annotations/Inject.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.injection.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Specifies that a field is a target for dependency injection. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Inject { +} diff --git a/common/src/main/java/com/dfsek/terra/api/injection/exception/InjectionException.java b/common/src/main/java/com/dfsek/terra/api/injection/exception/InjectionException.java new file mode 100644 index 000000000..314dd5e93 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/injection/exception/InjectionException.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.api.injection.exception; + +import com.dfsek.terra.api.injection.Injector; + +/** + * Thrown when dynamic dependency injection cannot be completed by an {@link Injector}. + */ +public class InjectionException extends Exception { + private static final long serialVersionUID = -6929631447064215387L; + + public InjectionException(String message) { + super(message); + } + + public InjectionException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/math/MathUtil.java b/common/src/main/java/com/dfsek/terra/api/math/MathUtil.java index 8dd83ee90..77c1a43cf 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/MathUtil.java +++ b/common/src/main/java/com/dfsek/terra/api/math/MathUtil.java @@ -1,7 +1,7 @@ package com.dfsek.terra.api.math; import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.world.generation.math.Sampler; +import com.dfsek.terra.world.generation.math.samplers.Sampler; import net.jafama.FastMath; import java.util.List; diff --git a/common/src/main/java/com/dfsek/terra/api/math/ProbabilityCollection.java b/common/src/main/java/com/dfsek/terra/api/math/ProbabilityCollection.java deleted file mode 100644 index 6d785e1d7..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/ProbabilityCollection.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.dfsek.terra.api.math; - -import com.dfsek.terra.api.math.noise.NoiseSampler; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Random; -import java.util.Set; - -@SuppressWarnings("unchecked") -public class ProbabilityCollection { - private final Set cont = new HashSet<>(); - private Object[] array = new Object[0]; - private int size; - - public com.dfsek.terra.api.math.ProbabilityCollection add(E item, int probability) { - if(!cont.contains(item)) size++; - cont.add(item); - int oldLength = array.length; - Object[] newArray = new Object[array.length + probability]; - System.arraycopy(array, 0, newArray, 0, array.length); // Expand array. - array = newArray; - for(int i = oldLength; i < array.length; i++) array[i] = item; - return this; - } - - public E get(Random r) { - if(array.length == 0) return null; - return (E) array[r.nextInt(array.length)]; - } - - public E get(NoiseSampler n, double x, double y, double z) { - if(array.length == 0) return null; - return (E) array[MathUtil.normalizeIndex(n.getNoise(x, y, z), array.length)]; - } - - public E get(NoiseSampler n, double x, double z) { - if(array.length == 0) return null; - return (E) array[MathUtil.normalizeIndex(n.getNoise(x, z), array.length)]; - } - - public int getTotalProbability() { - return array.length; - } - - public int size() { - return size; - } - - public Set getContents() { - return new HashSet<>(cont); - } - - public static final class Singleton extends ProbabilityCollection { - private final T single; - - public Singleton(T single) { - this.single = single; - } - - @Override - public ProbabilityCollection add(T item, int probability) { - throw new UnsupportedOperationException(); - } - - @Override - public T get(Random r) { - return single; - } - - @Override - public T get(NoiseSampler n, double x, double y, double z) { - return single; - } - - @Override - public T get(NoiseSampler n, double x, double z) { - return single; - } - - @Override - public int getTotalProbability() { - return 1; - } - - @Override - public int size() { - return 1; - } - - @Override - public Set getContents() { - return Collections.singleton(single); - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/Range.java b/common/src/main/java/com/dfsek/terra/api/math/Range.java index 6c5d3174a..ce8ae477d 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/Range.java +++ b/common/src/main/java/com/dfsek/terra/api/math/Range.java @@ -24,7 +24,7 @@ public class Range implements Iterable { return max; } - public com.dfsek.terra.api.math.Range setMax(int max) { + public Range setMax(int max) { this.max = max; return this; } @@ -33,7 +33,7 @@ public class Range implements Iterable { return min; } - public com.dfsek.terra.api.math.Range setMin(int min) { + public Range setMin(int min) { this.min = min; return this; } @@ -42,35 +42,35 @@ public class Range implements Iterable { return max - min; } - public com.dfsek.terra.api.math.Range multiply(int mult) { + public Range multiply(int mult) { min *= mult; max *= mult; return this; } - public com.dfsek.terra.api.math.Range reflect(int pt) { - return new com.dfsek.terra.api.math.Range(2 * pt - this.getMax(), 2 * pt - this.getMin()); + public Range reflect(int pt) { + return new Range(2 * pt - this.getMax(), 2 * pt - this.getMin()); } public int get(Random r) { return r.nextInt((max - min) + 1) + min; } - public com.dfsek.terra.api.math.Range intersects(com.dfsek.terra.api.math.Range other) { + public Range intersects(com.dfsek.terra.api.math.Range other) { try { - return new com.dfsek.terra.api.math.Range(FastMath.max(this.getMin(), other.getMin()), FastMath.min(this.getMax(), other.getMax())); + return new Range(FastMath.max(this.getMin(), other.getMin()), FastMath.min(this.getMax(), other.getMax())); } catch(IllegalArgumentException e) { return null; } } - public com.dfsek.terra.api.math.Range add(int add) { + public Range add(int add) { this.min += add; this.max += add; return this; } - public com.dfsek.terra.api.math.Range sub(int sub) { + public Range sub(int sub) { this.min -= sub; this.max -= sub; return this; @@ -89,7 +89,7 @@ public class Range implements Iterable { @Override public boolean equals(Object obj) { if(!(obj instanceof com.dfsek.terra.api.math.Range)) return false; - com.dfsek.terra.api.math.Range other = (com.dfsek.terra.api.math.Range) obj; + Range other = (com.dfsek.terra.api.math.Range) obj; return other.getMin() == this.getMin() && other.getMax() == this.getMax(); } @@ -100,10 +100,10 @@ public class Range implements Iterable { } private static class RangeIterator implements Iterator { - private final com.dfsek.terra.api.math.Range m; + private final Range m; private Integer current; - public RangeIterator(com.dfsek.terra.api.math.Range m) { + public RangeIterator(Range m) { this.m = m; current = m.getMin(); } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/ExpressionSampler.java b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/ExpressionSampler.java index 9b1fbbc4c..8ca8f2333 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/ExpressionSampler.java +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/ExpressionSampler.java @@ -14,7 +14,7 @@ import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; import java.util.Map; /** - * Sampler implementation using Paralithic expression + * Sampler3D implementation using Paralithic expression */ public class ExpressionSampler implements NoiseSampler { private final Expression expression; diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/ConstantSampler.java b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/ConstantSampler.java index a81756b92..203a1a85f 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/ConstantSampler.java +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/ConstantSampler.java @@ -1,7 +1,7 @@ package com.dfsek.terra.api.math.noise.samplers.noise; /** - * Sampler implementation that returns a constant. + * Sampler3D implementation that returns a constant. */ public class ConstantSampler extends NoiseFunction { private final double constant; diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/GaborNoiseSampler.java b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/GaborNoiseSampler.java new file mode 100644 index 000000000..93f006dc4 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/GaborNoiseSampler.java @@ -0,0 +1,105 @@ +package com.dfsek.terra.api.math.noise.samplers.noise; + +import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler; +import net.jafama.FastMath; + +public class GaborNoiseSampler extends NoiseFunction { + private final WhiteNoiseSampler rand; + private double k = 1.0; + private double a = 0.1; + private double f0 = 0.625; + private double kernelRadius = (FastMath.sqrt(-FastMath.log(0.05) / Math.PI) / a); + private double omega0 = Math.PI * 0.25; + private boolean isotropic = true; + private double impulsesPerKernel = 64d; + private double impulseDensity = (impulsesPerKernel / (Math.PI * kernelRadius * kernelRadius)); + + private double impulsesPerCell = impulseDensity * kernelRadius * kernelRadius; + private double g = FastMath.exp(-impulsesPerCell); + + + public GaborNoiseSampler(int seed) { + super(seed); + rand = new WhiteNoiseSampler(seed); + } + + public void setIsotropic(boolean isotropic) { + this.isotropic = isotropic; + } + + public void setImpulsesPerKernel(double impulsesPerKernel) { + this.impulsesPerKernel = impulsesPerKernel; + recalculateRadiusAndDensity(); + } + + public void setA(double a) { + this.a = a; + recalculateRadiusAndDensity(); + } + + public void setFrequency0(double f0) { + this.f0 = f0; + } + + public void setRotation(double omega0) { + this.omega0 = Math.PI * omega0; + } + + public void setDeviation(double k) { + this.k = k; + } + + private void recalculateRadiusAndDensity() { + kernelRadius = (FastMath.sqrt(-FastMath.log(0.05) / Math.PI) / this.a); + impulseDensity = (impulsesPerKernel / (Math.PI * kernelRadius * kernelRadius)); + impulsesPerCell = impulseDensity * kernelRadius * kernelRadius; + g = FastMath.exp(-impulsesPerCell); + } + + @Override + public double getNoiseRaw(int seed, double x, double z) { + return gaborNoise(seed, x, z); + } + + @Override + public double getNoiseRaw(int seed, double x, double y, double z) { + return gaborNoise(seed, x, z); + } + + private double gaborNoise(int seed, double x, double y) { + x /= kernelRadius; + y /= kernelRadius; + int xi = fastFloor(x); + int yi = fastFloor(y); + double xf = x - xi; + double yf = y - yi; + double noise = 0; + for(int dx = -1; dx <= 1; dx++) { + for(int dz = -1; dz <= 1; dz++) { + noise += calculateCell(seed, xi + dx, yi + dz, xf - dx, yf - dz); + } + } + return noise; + } + + private double calculateCell(int seed, int xi, int yi, double x, double y) { + long mashedSeed = murmur64(31L * xi + yi) + seed; + + double gaussianSource = (rand.getNoiseRaw(mashedSeed++) + 1) / 2; + int impulses = 0; + while(gaussianSource > g) { + impulses++; + gaussianSource *= (rand.getNoiseRaw(mashedSeed++) + 1) / 2; + } + + double noise = 0; + for(int i = 0; i < impulses; i++) { + noise += rand.getNoiseRaw(mashedSeed++) * gabor(isotropic ? (rand.getNoiseRaw(mashedSeed++) + 1) * Math.PI : omega0, x * kernelRadius, y * kernelRadius); + } + return noise; + } + + private double gabor(double omega_0, double x, double y) { + return k * (FastMath.exp(-Math.PI * (a * a) * (x * x + y * y)) * fastCos(2 * Math.PI * f0 * (x * fastCos(omega_0) + y * fastSin(omega_0)))); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/NoiseFunction.java b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/NoiseFunction.java index 6c5829f44..1266c3762 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/NoiseFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/NoiseFunction.java @@ -22,6 +22,8 @@ public abstract class NoiseFunction implements NoiseSampler { return f >= 0 ? (int) f : (int) f - 1; } + static final int precision = 100; + protected static int hash(int seed, int xPrimed, int yPrimed, int zPrimed) { int hash = seed ^ xPrimed ^ yPrimed ^ zPrimed; @@ -36,6 +38,8 @@ public abstract class NoiseFunction implements NoiseSampler { return hash; } + static final int modulus = 360 * precision; + protected static int fastRound(double f) { return f >= 0 ? (int) (f + 0.5f) : (int) (f - 0.5); } @@ -73,6 +77,48 @@ public abstract class NoiseFunction implements NoiseSampler { return FastMath.sqrt(f); } + static final double[] sin = new double[360 * 100]; // lookup table + + static { + for(int i = 0; i < sin.length; i++) { + sin[i] = (float) Math.sin((double) (i) / (precision)); + } + } + + protected static int fastCeil(double f) { + int i = (int) f; + if(i < f) i++; + return i; + } + + /** + * Murmur64 hashing function + * + * @param h Input value + * @return Hashed value + */ + protected static long murmur64(long h) { + h ^= h >>> 33; + h *= 0xff51afd7ed558ccdL; + h ^= h >>> 33; + h *= 0xc4ceb9fe1a85ec53L; + h ^= h >>> 33; + return h; + } + + private static double sinLookup(int a) { + return a >= 0 ? sin[a % (modulus)] : -sin[-a % (modulus)]; + } + + protected static double fastSin(double a) { + return sinLookup((int) (a * precision + 0.5f)); + } + + protected static double fastCos(double a) { + return sinLookup((int) ((a + Math.PI / 2) * precision + 0.5f)); + } + + public void setSeed(int seed) { this.seed = seed; } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/random/WhiteNoiseSampler.java b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/random/WhiteNoiseSampler.java index 80660949f..962ca2486 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/random/WhiteNoiseSampler.java +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/random/WhiteNoiseSampler.java @@ -12,38 +12,41 @@ public class WhiteNoiseSampler extends NoiseFunction { super(seed); } + public double getNoiseRaw(long seed) { + return (Double.longBitsToDouble((murmur64(seed) & 0x000fffffffffffffL) | POSITIVE_POW1) - 1.5) * 2; + } + @Override public double getNoiseRaw(int seed, double x, double y) { - long hashX = Double.doubleToRawLongBits(x) ^ seed; - long hashZ = Double.doubleToRawLongBits(y) ^ seed; - long hash = ((hashX ^ (hashX >>> 32)) + ((hashZ ^ (hashZ >>> 32)) << 32)) ^ seed; - long base = (murmur64(hash) & 0x000fffffffffffffL) - | POSITIVE_POW1; // Sign and exponent - return (Double.longBitsToDouble(base) - 1.5) * 2; + return (getNoiseUnmapped(seed, x, y) - 1.5) * 2; } @Override public double getNoiseRaw(int seed, double x, double y, double z) { + return (getNoiseUnmapped(seed, x, y, z) - 1.5) * 2; + } + + public double getNoiseUnmapped(int seed, double x, double y, double z) { + long base = ((randomBits(seed, x, y, z)) & 0x000fffffffffffffL) | POSITIVE_POW1; // Sign and exponent + return Double.longBitsToDouble(base); + } + + public double getNoiseUnmapped(int seed, double x, double y) { + long base = (randomBits(seed, x, y) & 0x000fffffffffffffL) | POSITIVE_POW1; // Sign and exponent + return Double.longBitsToDouble(base); + } + + public long randomBits(int seed, double x, double y, double z) { long hashX = Double.doubleToRawLongBits(x) ^ seed; long hashZ = Double.doubleToRawLongBits(y) ^ seed; long hash = (((hashX ^ (hashX >>> 32)) + ((hashZ ^ (hashZ >>> 32)) << 32)) ^ seed) + Double.doubleToRawLongBits(z); - long base = ((murmur64(hash)) & 0x000fffffffffffffL) - | POSITIVE_POW1; // Sign and exponent - return (Double.longBitsToDouble(base) - 1.5) * 2; + return murmur64(hash); } - /** - * Murmur64 hashing function - * - * @param h Input value - * @return Hashed value - */ - private static long murmur64(long h) { - h ^= h >>> 33; - h *= 0xff51afd7ed558ccdL; - h ^= h >>> 33; - h *= 0xc4ceb9fe1a85ec53L; - h ^= h >>> 33; - return h; + public long randomBits(int seed, double x, double y) { + long hashX = Double.doubleToRawLongBits(x) ^ seed; + long hashZ = Double.doubleToRawLongBits(y) ^ seed; + long hash = ((hashX ^ (hashX >>> 32)) + ((hashZ ^ (hashZ >>> 32)) << 32)) ^ seed; + return murmur64(hash); } } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/SimplexSampler.java b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/SimplexSampler.java new file mode 100644 index 000000000..b12a75d21 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/SimplexSampler.java @@ -0,0 +1,243 @@ +package com.dfsek.terra.api.math.noise.samplers.noise.simplex; + +public class SimplexSampler extends SimplexStyleSampler { + private static final Double2[] GRAD_2D = { + new Double2(-1, -1), new Double2(1, -1), new Double2(-1, 1), new Double2(1, 1), + new Double2(0, -1), new Double2(-1, 0), new Double2(0, 1), new Double2(1, 0), + }; + private static final Double3[] GRAD_3D = { + new Double3(1, 1, 0), new Double3(-1, 1, 0), new Double3(1, -1, 0), new Double3(-1, -1, 0), + new Double3(1, 0, 1), new Double3(-1, 0, 1), new Double3(1, 0, -1), new Double3(-1, 0, -1), + new Double3(0, 1, 1), new Double3(0, -1, 1), new Double3(0, 1, -1), new Double3(0, -1, -1), + new Double3(1, 1, 0), new Double3(0, -1, 1), new Double3(-1, 1, 0), new Double3(0, -1, -1), + }; + + private static final double F2 = 1.0 / 2.0; + private static final double F3 = (1.0 / 3.0); + private static final double G2 = 1.0 / 4.0; + private static final double G3 = (1.0 / 6.0); + private static final double G33 = G3 * 3 - 1; + + private static final int X_PRIME = 1619; + private static final int Y_PRIME = 31337; + private static final int Z_PRIME = 6971; + + + public SimplexSampler(int seed) { + super(seed); + } + + private static double gradCoord3D(int seed, int x, int y, int z, double xd, double yd, double zd) { + int hash = seed; + hash ^= X_PRIME * x; + hash ^= Y_PRIME * y; + hash ^= Z_PRIME * z; + + hash = hash * hash * hash * 60493; + hash = (hash >> 13) ^ hash; + + Double3 g = GRAD_3D[hash & 15]; + + return xd * g.x + yd * g.y + zd * g.z; + } + + private static double gradCoord2D(int seed, int x, int y, double xd, double yd) { + int hash = seed; + hash ^= X_PRIME * x; + hash ^= Y_PRIME * y; + + hash = hash * hash * hash * 60493; + hash = (hash >> 13) ^ hash; + + Double2 g = GRAD_2D[hash & 7]; + + return xd * g.x + yd * g.y; + } + + @Override + public double getNoiseRaw(int seed, double x, double y) { + double t = (x + y) * F2; + int i = fastFloor(x + t); + int j = fastFloor(y + t); + + t = (i + j) * G2; + double X0 = i - t; + double Y0 = j - t; + + double x0 = x - X0; + double y0 = y - Y0; + + int i1, j1; + if(x0 > y0) { + i1 = 1; + j1 = 0; + } else { + i1 = 0; + j1 = 1; + } + + double x1 = x0 - i1 + G2; + double y1 = y0 - j1 + G2; + double x2 = x0 - 1 + F2; + double y2 = y0 - 1 + F2; + + double n0, n1, n2; + + t = 0.5 - x0 * x0 - y0 * y0; + if(t < 0) { + n0 = 0; + } else { + t *= t; + n0 = t * t * gradCoord2D(seed, i, j, x0, y0); + } + + t = 0.5 - x1 * x1 - y1 * y1; + if(t < 0) { + n1 = 0; + } else { + t *= t; + n1 = t * t * gradCoord2D(seed, i + i1, j + j1, x1, y1); + } + + t = 0.5 - x2 * x2 - y2 * y2; + if(t < 0) { + n2 = 0; + } else { + t *= t; + n2 = t * t * gradCoord2D(seed, i + 1, j + 1, x2, y2); + } + + return 50 * (n0 + n1 + n2); + } + + @Override + public double getNoiseRaw(int seed, double x, double y, double z) { + double t = (x + y + z) * F3; + int i = fastFloor(x + t); + int j = fastFloor(y + t); + int k = fastFloor(z + t); + + t = (i + j + k) * G3; + double x0 = x - (i - t); + double y0 = y - (j - t); + double z0 = z - (k - t); + + int i1, j1, k1; + int i2, j2, k2; + + if(x0 >= y0) { + if(y0 >= z0) { + i1 = 1; + j1 = 0; + k1 = 0; + i2 = 1; + j2 = 1; + k2 = 0; + } else if(x0 >= z0) { + i1 = 1; + j1 = 0; + k1 = 0; + i2 = 1; + j2 = 0; + k2 = 1; + } else // x0 < z0 + { + i1 = 0; + j1 = 0; + k1 = 1; + i2 = 1; + j2 = 0; + k2 = 1; + } + } else // x0 < y0 + { + if(y0 < z0) { + i1 = 0; + j1 = 0; + k1 = 1; + i2 = 0; + j2 = 1; + k2 = 1; + } else if(x0 < z0) { + i1 = 0; + j1 = 1; + k1 = 0; + i2 = 0; + j2 = 1; + k2 = 1; + } else // x0 >= z0 + { + i1 = 0; + j1 = 1; + k1 = 0; + i2 = 1; + j2 = 1; + k2 = 0; + } + } + + double x1 = x0 - i1 + G3; + double y1 = y0 - j1 + G3; + double z1 = z0 - k1 + G3; + double x2 = x0 - i2 + F3; + double y2 = y0 - j2 + F3; + double z2 = z0 - k2 + F3; + double x3 = x0 + G33; + double y3 = y0 + G33; + double z3 = z0 + G33; + + double n0, n1, n2, n3; + + t = 0.6 - x0 * x0 - y0 * y0 - z0 * z0; + if(t < 0) n0 = 0; + else { + t *= t; + n0 = t * t * gradCoord3D(seed, i, j, k, x0, y0, z0); + } + + t = 0.6 - x1 * x1 - y1 * y1 - z1 * z1; + if(t < 0) { + n1 = 0; + } else { + t *= t; + n1 = t * t * gradCoord3D(seed, i + i1, j + j1, k + k1, x1, y1, z1); + } + + t = 0.6 - x2 * x2 - y2 * y2 - z2 * z2; + if(t < 0) { + n2 = 0; + } else { + t *= t; + n2 = t * t * gradCoord3D(seed, i + i2, j + j2, k + k2, x2, y2, z2); + } + + t = 0.6 - x3 * x3 - y3 * y3 - z3 * z3; + if(t < 0) { + n3 = 0; + } else { + t *= t; + n3 = t * t * gradCoord3D(seed, i + 1, j + 1, k + 1, x3, y3, z3); + } + + return 32 * (n0 + n1 + n2 + n3); + } + + private static class Double2 { + public final double x, y; + + public Double2(double x, double y) { + this.x = x; + this.y = y; + } + } + + private static class Double3 { + public final double x, y, z; + + public Double3(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/math/paralithic/noise/NoiseFunction2.java b/common/src/main/java/com/dfsek/terra/api/math/paralithic/noise/NoiseFunction2.java index 3b51cdd48..f4a516375 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/paralithic/noise/NoiseFunction2.java +++ b/common/src/main/java/com/dfsek/terra/api/math/paralithic/noise/NoiseFunction2.java @@ -1,7 +1,7 @@ package com.dfsek.terra.api.math.paralithic.noise; import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.util.hash.HashMapDoubleDouble; +import com.dfsek.terra.api.util.hash.HashMapDoubleDouble; diff --git a/common/src/main/java/com/dfsek/terra/api/math/vector/Location.java b/common/src/main/java/com/dfsek/terra/api/math/vector/Location.java index a030f9e49..de01cce98 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/vector/Location.java +++ b/common/src/main/java/com/dfsek/terra/api/math/vector/Location.java @@ -170,4 +170,9 @@ public class Location implements Cloneable { public String toString() { return "[" + world + ": (" + getX() + ", " + getY() + ", " + getZ() + ")]"; } + + public Location multiply(double v) { + vector.multiply(v); + return this; + } } diff --git a/common/src/main/java/com/dfsek/terra/api/platform/Player.java b/common/src/main/java/com/dfsek/terra/api/platform/Player.java deleted file mode 100644 index 136727749..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/Player.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.dfsek.terra.api.platform; - -import com.dfsek.terra.api.platform.entity.Entity; - -public interface Player extends Entity { -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/Block.java b/common/src/main/java/com/dfsek/terra/api/platform/block/Block.java index 47242d6e2..b6132ef0a 100644 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/Block.java +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/Block.java @@ -11,7 +11,9 @@ public interface Block extends Handle { BlockState getState(); - Block getRelative(BlockFace face); + default Block getRelative(BlockFace face) { + return getRelative(face, 1); + } Block getRelative(BlockFace face, int len); @@ -19,7 +21,9 @@ public interface Block extends Handle { Location getLocation(); - MaterialData getType(); + default BlockType getType() { + return getBlockData().getBlockType(); + } int getX(); diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/BlockData.java b/common/src/main/java/com/dfsek/terra/api/platform/block/BlockData.java index d58979fa6..3082a2184 100644 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/BlockData.java +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/BlockData.java @@ -3,11 +3,16 @@ package com.dfsek.terra.api.platform.block; import com.dfsek.terra.api.platform.Handle; public interface BlockData extends Cloneable, Handle { - MaterialData getMaterial(); - boolean matches(MaterialData materialData); + BlockType getBlockType(); + + boolean matches(BlockData other); BlockData clone(); String getAsString(); + + boolean isAir(); + + boolean isStructureVoid(); } diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/BlockType.java b/common/src/main/java/com/dfsek/terra/api/platform/block/BlockType.java new file mode 100644 index 000000000..d7c6c160d --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/BlockType.java @@ -0,0 +1,9 @@ +package com.dfsek.terra.api.platform.block; + +import com.dfsek.terra.api.platform.Handle; + +public interface BlockType extends Handle { + BlockData getDefaultData(); + + boolean isSolid(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/MaterialData.java b/common/src/main/java/com/dfsek/terra/api/platform/block/MaterialData.java deleted file mode 100644 index c5f3037b1..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/MaterialData.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dfsek.terra.api.platform.block; - -import com.dfsek.terra.api.platform.Handle; - -public interface MaterialData extends Handle { - boolean matches(MaterialData other); - - boolean matches(BlockData other); - - boolean isSolid(); - - boolean isAir(); - - double getMaxDurability(); - - BlockData createBlockData(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/entity/Entity.java b/common/src/main/java/com/dfsek/terra/api/platform/entity/Entity.java index e69ffbcbc..51c9be6e5 100644 --- a/common/src/main/java/com/dfsek/terra/api/platform/entity/Entity.java +++ b/common/src/main/java/com/dfsek/terra/api/platform/entity/Entity.java @@ -3,7 +3,12 @@ package com.dfsek.terra.api.platform.entity; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.CommandSender; import com.dfsek.terra.api.platform.Handle; +import com.dfsek.terra.api.platform.world.World; public interface Entity extends Handle, CommandSender { Location getLocation(); + + void setLocation(Location location); + + World getWorld(); } diff --git a/common/src/main/java/com/dfsek/terra/api/platform/entity/Player.java b/common/src/main/java/com/dfsek/terra/api/platform/entity/Player.java new file mode 100644 index 000000000..43a002089 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/entity/Player.java @@ -0,0 +1,4 @@ +package com.dfsek.terra.api.platform.entity; + +public interface Player extends Entity { +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/handle/ItemHandle.java b/common/src/main/java/com/dfsek/terra/api/platform/handle/ItemHandle.java index fe2fe39d0..1c76e225d 100644 --- a/common/src/main/java/com/dfsek/terra/api/platform/handle/ItemHandle.java +++ b/common/src/main/java/com/dfsek/terra/api/platform/handle/ItemHandle.java @@ -1,13 +1,13 @@ package com.dfsek.terra.api.platform.handle; -import com.dfsek.terra.api.platform.block.MaterialData; -import com.dfsek.terra.api.platform.inventory.ItemStack; +import com.dfsek.terra.api.platform.inventory.Item; import com.dfsek.terra.api.platform.inventory.item.Enchantment; import java.util.Set; public interface ItemHandle { - ItemStack newItemStack(MaterialData material, int amount); + + Item createItem(String data); Enchantment getEnchantment(String id); diff --git a/common/src/main/java/com/dfsek/terra/api/platform/handle/WorldHandle.java b/common/src/main/java/com/dfsek/terra/api/platform/handle/WorldHandle.java index 373d44f15..776b695a5 100644 --- a/common/src/main/java/com/dfsek/terra/api/platform/handle/WorldHandle.java +++ b/common/src/main/java/com/dfsek/terra/api/platform/handle/WorldHandle.java @@ -1,23 +1,26 @@ package com.dfsek.terra.api.platform.handle; -import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; import com.dfsek.terra.api.platform.entity.EntityType; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.util.generic.pair.Pair; /** * Interface to be implemented for world manipulation. */ public interface WorldHandle { - void setBlockData(Block block, BlockData data, boolean physics); - - BlockData getBlockData(Block block); - - MaterialData getType(Block block); - BlockData createBlockData(String data); - MaterialData createMaterialData(String data); - EntityType getEntity(String id); + + /** + * Get the locations selected by a player. (Usually via WorldEdit) + * + * @param player Player to get locations for + * @return Pair of locations. + */ + default Pair getSelectedLocation(Player player) { + throw new UnsupportedOperationException("Cannot get selection on this platform."); + } } diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/Item.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/Item.java new file mode 100644 index 000000000..4fa70ede3 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/inventory/Item.java @@ -0,0 +1,12 @@ +package com.dfsek.terra.api.platform.inventory; + +import com.dfsek.terra.api.platform.Handle; + +/** + * An inventory item. + */ +public interface Item extends Handle { + ItemStack newItemStack(int amount); + + double getMaxDurability(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/ItemStack.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/ItemStack.java index 95b1d299a..dfa8d9719 100644 --- a/common/src/main/java/com/dfsek/terra/api/platform/inventory/ItemStack.java +++ b/common/src/main/java/com/dfsek/terra/api/platform/inventory/ItemStack.java @@ -1,17 +1,14 @@ package com.dfsek.terra.api.platform.inventory; import com.dfsek.terra.api.platform.Handle; -import com.dfsek.terra.api.platform.block.MaterialData; import com.dfsek.terra.api.platform.inventory.item.ItemMeta; -public interface ItemStack extends Handle, Cloneable { +public interface ItemStack extends Handle { int getAmount(); void setAmount(int i); - MaterialData getType(); - - ItemStack clone(); + Item getType(); ItemMeta getItemMeta(); diff --git a/common/src/main/java/com/dfsek/terra/api/platform/package-info.java b/common/src/main/java/com/dfsek/terra/api/platform/package-info.java index f1b97f5ed..44377a381 100644 --- a/common/src/main/java/com/dfsek/terra/api/platform/package-info.java +++ b/common/src/main/java/com/dfsek/terra/api/platform/package-info.java @@ -1,4 +1,6 @@ /** * API for platform implementations. Mostly interfaces to be implemented by platform delegates. + *

+ * Interfaces in this package generally should not be implemented by addons. */ package com.dfsek.terra.api.platform; diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/World.java b/common/src/main/java/com/dfsek/terra/api/platform/world/World.java index 57ee58b7d..1dbcd85a6 100644 --- a/common/src/main/java/com/dfsek/terra/api/platform/world/World.java +++ b/common/src/main/java/com/dfsek/terra/api/platform/world/World.java @@ -25,11 +25,19 @@ public interface World extends Handle { Chunk getChunkAt(int x, int z); + default Chunk getChunkAt(Location location) { + return getChunkAt(location.getBlockX() >> 4, location.getBlockZ() >> 4); + } + File getWorldFolder(); Block getBlockAt(int x, int y, int z); - Block getBlockAt(Location l); + default Block getBlockAt(Location l) { + return getBlockAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()); + } Entity spawnEntity(Location location, EntityType entityType); + + int getMinHeight(); } diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/generator/ChunkData.java b/common/src/main/java/com/dfsek/terra/api/platform/world/generator/ChunkData.java new file mode 100644 index 000000000..bb7f164a4 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/world/generator/ChunkData.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.platform.world.generator; + +import com.dfsek.terra.api.platform.world.ChunkAccess; + +public interface ChunkData extends ChunkAccess { + /** + * Get the maximum height for the chunk. + *

+ * Setting blocks at or above this height will do nothing. + * + * @return the maximum height + */ + int getMaxHeight(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/generator/ChunkGenerator.java b/common/src/main/java/com/dfsek/terra/api/platform/world/generator/ChunkGenerator.java index 63676d31c..da3594011 100644 --- a/common/src/main/java/com/dfsek/terra/api/platform/world/generator/ChunkGenerator.java +++ b/common/src/main/java/com/dfsek/terra/api/platform/world/generator/ChunkGenerator.java @@ -1,43 +1,7 @@ package com.dfsek.terra.api.platform.world.generator; import com.dfsek.terra.api.platform.Handle; -import com.dfsek.terra.api.platform.world.BiomeGrid; -import com.dfsek.terra.api.platform.world.ChunkAccess; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.Random; public interface ChunkGenerator extends Handle { - boolean isParallelCapable(); - boolean shouldGenerateCaves(); - - boolean shouldGenerateDecorations(); - - boolean shouldGenerateMobs(); - - boolean shouldGenerateStructures(); - - ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome); - - - List getDefaultPopulators(World world); - - @Nullable - TerraChunkGenerator getTerraGenerator(); - - interface ChunkData extends ChunkAccess { - /** - * Get the maximum height for the chunk. - *

- * Setting blocks at or above this height will do nothing. - * - * @return the maximum height - */ - int getMaxHeight(); - } } diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/generator/GeneratorWrapper.java b/common/src/main/java/com/dfsek/terra/api/platform/world/generator/GeneratorWrapper.java index 4de6bdc2b..127f9e5bf 100644 --- a/common/src/main/java/com/dfsek/terra/api/platform/world/generator/GeneratorWrapper.java +++ b/common/src/main/java/com/dfsek/terra/api/platform/world/generator/GeneratorWrapper.java @@ -1,6 +1,9 @@ package com.dfsek.terra.api.platform.world.generator; import com.dfsek.terra.api.platform.Handle; +import com.dfsek.terra.api.world.generation.TerraChunkGenerator; public interface GeneratorWrapper extends Handle { + @Override + TerraChunkGenerator getHandle(); } diff --git a/common/src/main/java/com/dfsek/terra/api/registry/CheckedRegistry.java b/common/src/main/java/com/dfsek/terra/api/registry/CheckedRegistry.java new file mode 100644 index 000000000..9934c767b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/registry/CheckedRegistry.java @@ -0,0 +1,84 @@ +package com.dfsek.terra.api.registry; + +import com.dfsek.tectonic.exception.LoadException; +import com.dfsek.tectonic.loading.ConfigLoader; +import com.dfsek.terra.registry.OpenRegistry; +import com.dfsek.terra.registry.exception.DuplicateEntryException; + +import java.lang.reflect.Type; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +/** + * Wrapper for a registry that ensures checked additions. + * + * @param Type in registry + */ +public class CheckedRegistry implements Registry { + private final OpenRegistry registry; + + public CheckedRegistry(OpenRegistry registry) { + this.registry = registry; + } + + /** + * Add a value to this registry, checking whether it is present first. + * + * @param identifier Identifier to assign value. + * @param value Value to add. + * @throws DuplicateEntryException If an entry with the same identifier is already present. + */ + public void add(String identifier, T value) throws DuplicateEntryException { + registry.addChecked(identifier, value); + } + + /** + * Add a value to the registry, without checking presence beforehand. + *

+ * Use of this method is generally discouraged, as it is bad practice to overwrite registry values. + * + * @param identifier Identifier to assign value. + * @param value Value to add. + * @deprecated Use of {@link #add(String, Object)} is encouraged. + */ + @Deprecated + public void addUnchecked(String identifier, T value) { + registry.add(identifier, value); + } + + @Override + public T get(String identifier) { + return registry.get(identifier); + } + + @Override + public boolean contains(String identifier) { + return registry.contains(identifier); + } + + @Override + public void forEach(Consumer consumer) { + registry.forEach(consumer); + } + + @Override + public void forEach(BiConsumer consumer) { + registry.forEach(consumer); + } + + @Override + public Set entries() { + return registry.entries(); + } + + @Override + public Set keys() { + return registry.keys(); + } + + @Override + public T load(Type t, Object c, ConfigLoader loader) throws LoadException { + return registry.load(t, c, loader); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/registry/LockedRegistry.java b/common/src/main/java/com/dfsek/terra/api/registry/LockedRegistry.java new file mode 100644 index 000000000..227656c4d --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/registry/LockedRegistry.java @@ -0,0 +1,57 @@ +package com.dfsek.terra.api.registry; + +import com.dfsek.tectonic.exception.LoadException; +import com.dfsek.tectonic.loading.ConfigLoader; + +import java.lang.reflect.Type; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +/** + * Wrapper for a registry that forbids all write access. + * + * @param Type in registry + */ +public class LockedRegistry implements Registry { + private final Registry registry; + + public LockedRegistry(Registry registry) { + this.registry = registry; + } + + @Override + public T get(String identifier) { + return registry.get(identifier); + } + + @Override + public boolean contains(String identifier) { + return registry.contains(identifier); + } + + @Override + public void forEach(Consumer consumer) { + registry.forEach(consumer); + } + + @Override + public void forEach(BiConsumer consumer) { + registry.forEach(consumer); + } + + @Override + public Set entries() { + return registry.entries(); + } + + @Override + public Set keys() { + return registry.keys(); + } + + @Override + public T load(Type t, Object c, ConfigLoader loader) throws LoadException { + return registry.load(t, c, loader); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/registry/Registry.java b/common/src/main/java/com/dfsek/terra/api/registry/Registry.java new file mode 100644 index 000000000..773d784ca --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/registry/Registry.java @@ -0,0 +1,53 @@ +package com.dfsek.terra.api.registry; + +import com.dfsek.tectonic.loading.TypeLoader; + +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +public interface Registry extends TypeLoader { + /** + * Get a value from the registry. + * + * @param identifier Identifier of value. + * @return Value matching the identifier, {@code null} if no value is present. + */ + T get(String identifier); + + /** + * Check if the registry contains a value. + * + * @param identifier Identifier of value. + * @return Whether the registry contains the value. + */ + boolean contains(String identifier); + + /** + * Perform the given action for every value in the registry. + * + * @param consumer Action to perform on value. + */ + void forEach(Consumer consumer); + + /** + * Perform an action for every key-value pair in the registry. + * + * @param consumer Action to perform on pair. + */ + void forEach(BiConsumer consumer); + + /** + * Get the entries of this registry as a {@link Set}. + * + * @return Set containing all entries. + */ + Set entries(); + + /** + * Get all the keys in this registry. + * + * @return Keys in registry + */ + Set keys(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/Entry.java b/common/src/main/java/com/dfsek/terra/api/structures/loot/Entry.java index 4da109325..81c48aab1 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/loot/Entry.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/loot/Entry.java @@ -1,7 +1,7 @@ package com.dfsek.terra.api.structures.loot; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.platform.inventory.Item; import com.dfsek.terra.api.platform.inventory.ItemStack; import com.dfsek.terra.api.structures.loot.functions.AmountFunction; import com.dfsek.terra.api.structures.loot.functions.DamageFunction; @@ -19,10 +19,9 @@ import java.util.Random; * Representation of a single item entry within a Loot Table pool. */ public class Entry { - private final MaterialData item; + private final Item item; private final long weight; private final List functions = new GlueList<>(); - private final TerraPlugin main; /** * Instantiates an Entry from a JSON representation. @@ -30,9 +29,8 @@ public class Entry { * @param entry The JSON Object to instantiate from. */ public Entry(JSONObject entry, TerraPlugin main) { - this.main = main; String id = entry.get("name").toString(); - this.item = main.getWorldHandle().createMaterialData(id); + this.item = main.getItemHandle().createItem(id); long weight1; try { @@ -85,7 +83,7 @@ public class Entry { * @return ItemStack - The ItemStack with all functions applied. */ public ItemStack getItem(Random r) { - ItemStack item = main.getItemHandle().newItemStack(this.item, 1); + ItemStack item = this.item.newItemStack(1); for(LootFunction f : functions) { item = f.apply(item, r); } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/LootTable.java b/common/src/main/java/com/dfsek/terra/api/structures/loot/LootTable.java index cdbc80296..886d72178 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/loot/LootTable.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/loot/LootTable.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.loot; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.platform.inventory.Inventory; import com.dfsek.terra.api.platform.inventory.ItemStack; import com.dfsek.terra.api.util.GlueList; @@ -58,7 +58,8 @@ public class LootTable { for(ItemStack stack : loot) { int attempts = 0; while(stack.getAmount() != 0 && attempts < 10) { - ItemStack newStack = stack.clone(); + ItemStack newStack = stack.getType().newItemStack(stack.getAmount()); + newStack.setItemMeta(stack.getItemMeta()); newStack.setAmount(1); int slot = r.nextInt(i.getSize()); ItemStack slotItem = i.getItem(slot); @@ -66,7 +67,8 @@ public class LootTable { i.setItem(slot, newStack); stack.setAmount(stack.getAmount() - 1); } else if(slotItem.getType().equals(newStack.getType())) { - ItemStack dep = newStack.clone(); + ItemStack dep = newStack.getType().newItemStack(newStack.getAmount()); + dep.setItemMeta(newStack.getItemMeta()); dep.setAmount(newStack.getAmount() + slotItem.getAmount()); i.setItem(slot, dep); stack.setAmount(stack.getAmount() - 1); diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/Pool.java b/common/src/main/java/com/dfsek/terra/api/structures/loot/Pool.java index 418d86332..e01a25bdb 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/loot/Pool.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/loot/Pool.java @@ -1,9 +1,9 @@ package com.dfsek.terra.api.structures.loot; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.platform.inventory.ItemStack; import com.dfsek.terra.api.util.GlueList; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import net.jafama.FastMath; import org.json.simple.JSONArray; import org.json.simple.JSONObject; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/DamageFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/DamageFunction.java index 704fdcfa8..189a0c100 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/DamageFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/DamageFunction.java @@ -33,8 +33,11 @@ public class DamageFunction implements LootFunction { */ @Override public ItemStack apply(ItemStack original, Random r) { + if(original == null) return null; + ItemMeta meta = original.getItemMeta(); + if(!(meta instanceof Damageable)) return original; double itemDurability = (r.nextDouble() * (max - min)) + min; - Damageable damage = (Damageable) original.getItemMeta(); + Damageable damage = (Damageable) meta; damage.setDamage((int) (original.getType().getMaxDurability() - (itemDurability / 100) * original.getType().getMaxDurability())); original.setItemMeta((ItemMeta) damage); return original; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/EnchantFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/EnchantFunction.java index badfe6979..50818d871 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/EnchantFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/EnchantFunction.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.loot.functions; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.platform.inventory.ItemStack; import com.dfsek.terra.api.platform.inventory.item.Enchantment; import com.dfsek.terra.api.platform.inventory.item.ItemMeta; @@ -35,6 +35,8 @@ public class EnchantFunction implements LootFunction { */ @Override public ItemStack apply(ItemStack original, Random r) { + if(original.getItemMeta() == null) return original; + double enchant = (r.nextDouble() * (max - min)) + min; List possible = new GlueList<>(); for(Enchantment ench : main.getItemHandle().getEnchantments()) { @@ -55,7 +57,7 @@ public class EnchantFunction implements LootFunction { try { meta.addEnchantment(chosen, FastMath.max(lvl, 1)); } catch(IllegalArgumentException e) { - main.getLogger().warning("Attempted to enchant " + original.getType() + " with " + chosen + " at level " + FastMath.max(lvl, 1) + ", but an unexpected exception occurred! Usually this is caused by a misbehaving enchantment plugin."); + main.logger().warning("Attempted to enchant " + original.getType() + " with " + chosen + " at level " + FastMath.max(lvl, 1) + ", but an unexpected exception occurred! Usually this is caused by a misbehaving enchantment plugin."); } } original.setItemMeta(meta); diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java b/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java index c68c7cb07..8ceb1bf28 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.structures.parser.Parser; @@ -28,10 +28,9 @@ import com.dfsek.terra.api.structures.structure.Rotation; import com.dfsek.terra.api.structures.structure.buffer.Buffer; import com.dfsek.terra.api.structures.structure.buffer.DirectBuffer; import com.dfsek.terra.api.structures.structure.buffer.StructureBuffer; -import com.dfsek.terra.registry.FunctionRegistry; +import com.dfsek.terra.registry.config.FunctionRegistry; import com.dfsek.terra.registry.config.LootRegistry; import com.dfsek.terra.registry.config.ScriptRegistry; -import com.dfsek.terra.world.generation.math.SamplerCache; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import net.jafama.FastMath; @@ -47,9 +46,9 @@ public class StructureScript { private final String id; private final Cache cache; private final TerraPlugin main; - String tempID; + private String tempID; - public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, SamplerCache cache, FunctionRegistry functionRegistry) throws ParseException { + public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, FunctionRegistry functionRegistry) throws ParseException { Parser parser; try { parser = new Parser(IOUtils.toString(inputStream)); @@ -57,8 +56,10 @@ public class StructureScript { throw new RuntimeException(e); } + functionRegistry.forEach(parser::registerFunction); // Register registry functions. + parser.registerFunction("block", new BlockFunctionBuilder(main)) - .registerFunction("check", new CheckFunctionBuilder(main, cache)) + .registerFunction("check", new CheckFunctionBuilder(main)) .registerFunction("structure", new StructureFunctionBuilder(registry, main)) .registerFunction("randomInt", new RandomFunctionBuilder()) .registerFunction("recursions", new RecursionsFunctionBuilder()) @@ -86,8 +87,6 @@ public class StructureScript { .registerFunction("max", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.max(number.doubleValue(), number2.doubleValue()))) .registerFunction("min", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.min(number.doubleValue(), number2.doubleValue()))); - functionRegistry.forEach(parser::registerFunction); // Register registry functions. - block = parser.parse(); this.id = parser.getID(); tempID = id; @@ -149,7 +148,7 @@ public class StructureScript { try { return !block.apply(arguments).getLevel().equals(Block.ReturnLevel.FAIL); } catch(RuntimeException e) { - main.getLogger().severe("Failed to generate structure at " + arguments.getBuffer().getOrigin() + ": " + e.getMessage()); + main.logger().severe("Failed to generate structure at " + arguments.getBuffer().getOrigin() + ": " + e.getMessage()); main.getDebugLogger().stack(e); return false; } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BiomeFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BiomeFunctionBuilder.java index 58c71b589..7c15c70b4 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BiomeFunctionBuilder.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BiomeFunctionBuilder.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script.builders; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.structures.parser.lang.Returnable; import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.api.structures.script.functions.BiomeFunction; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BlockFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BlockFunctionBuilder.java index ac0052165..41c4a0dfe 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BlockFunctionBuilder.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BlockFunctionBuilder.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script.builders; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.structures.parser.exceptions.ParseException; import com.dfsek.terra.api.structures.parser.lang.Returnable; import com.dfsek.terra.api.structures.parser.lang.constants.BooleanConstant; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/CheckFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/CheckFunctionBuilder.java index af024d8c2..4ac870f49 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/CheckFunctionBuilder.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/CheckFunctionBuilder.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script.builders; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.structures.parser.exceptions.ParseException; import com.dfsek.terra.api.structures.parser.lang.Returnable; import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; @@ -12,17 +12,15 @@ import java.util.List; public class CheckFunctionBuilder implements FunctionBuilder { private final TerraPlugin main; - private final SamplerCache cache; - public CheckFunctionBuilder(TerraPlugin main, SamplerCache cache) { + public CheckFunctionBuilder(TerraPlugin main) { this.main = main; - this.cache = cache; } @SuppressWarnings("unchecked") @Override public CheckFunction build(List> argumentList, Position position) throws ParseException { - return new CheckFunction(main, (Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), cache, position); + return new CheckFunction(main, (Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), position); } @Override diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/EntityFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/EntityFunctionBuilder.java index 6582d617e..dd66a3d84 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/EntityFunctionBuilder.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/EntityFunctionBuilder.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script.builders; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.structures.parser.exceptions.ParseException; import com.dfsek.terra.api.structures.parser.lang.Returnable; import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/LootFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/LootFunctionBuilder.java index b2a39c92a..fe4634848 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/LootFunctionBuilder.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/LootFunctionBuilder.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script.builders; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.structures.parser.lang.Returnable; import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.api.structures.script.functions.LootFunction; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/PullFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/PullFunctionBuilder.java index 54eb8fc27..9b55da244 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/PullFunctionBuilder.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/PullFunctionBuilder.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script.builders; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.structures.parser.exceptions.ParseException; import com.dfsek.terra.api.structures.parser.lang.Returnable; import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StateFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StateFunctionBuilder.java index cbd37db8f..56c9ab2e3 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StateFunctionBuilder.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StateFunctionBuilder.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script.builders; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.structures.parser.exceptions.ParseException; import com.dfsek.terra.api.structures.parser.lang.Returnable; import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StructureFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StructureFunctionBuilder.java index 311cb4d1b..2b0be8468 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StructureFunctionBuilder.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StructureFunctionBuilder.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script.builders; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.structures.parser.exceptions.ParseException; import com.dfsek.terra.api.structures.parser.lang.Returnable; import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BiomeFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BiomeFunction.java index dd6a5bc0b..54eb7e280 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BiomeFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BiomeFunction.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script.functions; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Vector2; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; @@ -10,8 +10,8 @@ import com.dfsek.terra.api.structures.parser.lang.variables.Variable; import com.dfsek.terra.api.structures.script.TerraImplementationArguments; import com.dfsek.terra.api.structures.structure.RotationUtil; import com.dfsek.terra.api.structures.tokenizer.Position; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import net.jafama.FastMath; import java.util.Map; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java index 27e10da56..cf9c07ef5 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script.functions; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Vector2; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.BlockData; @@ -23,9 +23,11 @@ public class BlockFunction implements Function { private final Returnable x, y, z; private final Position position; private final Returnable overwrite; + private final TerraPlugin main; public BlockFunction(Returnable x, Returnable y, Returnable z, Returnable data, Returnable overwrite, TerraPlugin main, Position position) throws ParseException { this.position = position; + this.main = main; if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant", data.getPosition()); try { @@ -49,7 +51,7 @@ public class BlockFunction implements Function { RotationUtil.rotateVector(xz, arguments.getRotation()); RotationUtil.rotateBlockData(rot, arguments.getRotation().inverse()); - arguments.getBuffer().addItem(new BufferedBlock(rot, overwrite.apply(implementationArguments, variableMap)), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld())); + arguments.getBuffer().addItem(new BufferedBlock(rot, overwrite.apply(implementationArguments, variableMap), main), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld())); return null; } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckFunction.java index e82053b84..fee00e6c6 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckFunction.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script.functions; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Vector2; import com.dfsek.terra.api.math.vector.Vector3; @@ -12,8 +12,8 @@ import com.dfsek.terra.api.structures.parser.lang.variables.Variable; import com.dfsek.terra.api.structures.script.TerraImplementationArguments; import com.dfsek.terra.api.structures.structure.RotationUtil; import com.dfsek.terra.api.structures.tokenizer.Position; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.config.templates.BiomeTemplate; import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.generation.math.SamplerCache; @@ -25,22 +25,23 @@ public class CheckFunction implements Function { private final TerraPlugin main; private final Returnable x, y, z; private final Position position; - private final SamplerCache cache; - public CheckFunction(TerraPlugin main, Returnable x, Returnable y, Returnable z, SamplerCache cache, Position position) { + public CheckFunction(TerraPlugin main, Returnable x, Returnable y, Returnable z, Position position) { this.main = main; this.x = x; this.y = y; this.z = z; this.position = position; - this.cache = cache; } @Override public String apply(ImplementationArguments implementationArguments, Map> variableMap) { + + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue()); RotationUtil.rotateVector(xz, arguments.getRotation()); @@ -52,7 +53,8 @@ public class CheckFunction implements Function { private String apply(Location vector, World world) { TerraWorld tw = main.getWorld(world); - double comp = sample(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), world); + SamplerCache cache = tw.getConfig().getSamplerCache(); + double comp = sample(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), cache); if(comp > 0) return "LAND"; // If noise val is greater than zero, location will always be land. @@ -64,10 +66,10 @@ public class CheckFunction implements Function { return "OCEAN"; // Below sea level } - private double sample(int x, int y, int z, World w) { + private double sample(int x, int y, int z, SamplerCache cache) { int cx = FastMath.floorDiv(x, 16); int cz = FastMath.floorDiv(z, 16); - return cache.get(w, x, z).sample(x - (cx << 4), y, z - (cz << 4)); + return cache.get(x, z).sample(x - (cx << 4), y, z - (cz << 4)); } @Override diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/EntityFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/EntityFunction.java index 96ca732ce..547ae7a00 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/EntityFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/EntityFunction.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script.functions; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Vector2; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.entity.EntityType; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/LootFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/LootFunction.java index 5218f86a7..353294c73 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/LootFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/LootFunction.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script.functions; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Vector2; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.structures.loot.LootTable; @@ -45,7 +45,7 @@ public class LootFunction implements Function { LootTable table = registry.get(id); if(table == null) { - main.getLogger().severe("No such loot table " + id); + main.logger().severe("No such loot table " + id); return null; } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/PullFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/PullFunction.java index de1d56053..059aca0fa 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/PullFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/PullFunction.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script.functions; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Vector2; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.BlockData; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StateFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StateFunction.java index 812ca86bb..4e2e2c276 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StateFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StateFunction.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script.functions; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Vector2; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java index cd61d0ae0..7b9b38830 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.script.functions; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Vector2; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; @@ -57,7 +57,7 @@ public class StructureFunction implements Function { String app = id.apply(implementationArguments, variableMap); StructureScript script = registry.get(app); if(script == null) { - main.getLogger().severe("No such structure " + app); + main.logger().severe("No such structure " + app); return null; } @@ -66,7 +66,7 @@ public class StructureFunction implements Function { try { rotation1 = Rotation.valueOf(rotString); } catch(IllegalArgumentException e) { - main.getLogger().severe("Invalid rotation " + rotString); + main.logger().severe("Invalid rotation " + rotString); return null; } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/StructureBuffer.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/StructureBuffer.java index 6ff3029c6..7b4e49a2e 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/StructureBuffer.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/StructureBuffer.java @@ -22,11 +22,11 @@ public class StructureBuffer implements Buffer { } public void paste(Chunk chunk) { - bufferedItemMap.forEach(((vector3, item) -> { - Location current = origin.clone().add(vector3); + bufferedItemMap.forEach(((location, item) -> { + Location current = origin.clone().add(location); if(FastMath.floorDiv(current.getBlockX(), 16) != chunk.getX() || FastMath.floorDiv(current.getBlockZ(), 16) != chunk.getZ()) return; - item.paste(origin.clone().add(vector3)); + item.paste(chunk, current); })); } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedBlock.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedBlock.java index 932efbd15..efb706ea9 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedBlock.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedBlock.java @@ -1,5 +1,6 @@ package com.dfsek.terra.api.structures.structure.buffer.items; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.BlockData; @@ -7,15 +8,22 @@ import com.dfsek.terra.api.platform.block.BlockData; public class BufferedBlock implements BufferedItem { private final BlockData data; private final boolean overwrite; + private final TerraPlugin main; - public BufferedBlock(BlockData data, boolean overwrite) { + public BufferedBlock(BlockData data, boolean overwrite, TerraPlugin main) { this.data = data; this.overwrite = overwrite; + this.main = main; } @Override public void paste(Location origin) { Block block = origin.getBlock(); - if(overwrite || block.isEmpty()) block.setBlockData(data, false); + try { + if(overwrite || block.isEmpty()) block.setBlockData(data, false); + } catch(RuntimeException e) { + main.logger().severe("Failed to place block at location " + origin + ": " + e.getMessage()); + main.getDebugLogger().stack(e); + } } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedItem.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedItem.java index a4cfa2e17..7d6ddef2c 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedItem.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedItem.java @@ -1,7 +1,13 @@ package com.dfsek.terra.api.structures.structure.buffer.items; import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.world.Chunk; public interface BufferedItem { void paste(Location origin); + + default void paste(Chunk chunk, Location origin) { + origin.setWorld(chunk.getWorld()); // Fabric weirdness + paste(origin); + } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedLootApplication.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedLootApplication.java index 7b0c04234..5f69a6470 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedLootApplication.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedLootApplication.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.structure.buffer.items; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.state.BlockState; import com.dfsek.terra.api.platform.block.state.Container; @@ -18,12 +18,18 @@ public class BufferedLootApplication implements BufferedItem { @Override public void paste(Location origin) { - BlockState data = origin.getBlock().getState(); - if(!(data instanceof Container)) { - main.getLogger().severe("Failed to place loot at " + origin + "; block " + data + " is not container."); - return; + try { + BlockState data = origin.getBlock().getState(); + if(!(data instanceof Container)) { + main.logger().severe("Failed to place loot at " + origin + "; block " + data + " is not container."); + return; + } + Container container = (Container) data; + table.fillInventory(container.getInventory(), new FastRandom(origin.hashCode())); + data.update(false); + } catch(Exception e) { + main.logger().warning("Could not apply loot at " + origin + ": " + e.getMessage()); + main.getDebugLogger().stack(e); } - Container container = (Container) data; - table.fillInventory(container.getInventory(), new FastRandom(origin.hashCode())); } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedStateManipulator.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedStateManipulator.java index 6e11ea384..703ca2695 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedStateManipulator.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedStateManipulator.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.structures.structure.buffer.items; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.state.BlockState; @@ -15,12 +15,13 @@ public class BufferedStateManipulator implements BufferedItem { @Override public void paste(Location origin) { - BlockState state = origin.getBlock().getState(); try { + BlockState state = origin.getBlock().getState(); state.applyState(data); state.update(false); } catch(Exception e) { - main.getLogger().warning("Could not apply BlockState at " + origin + ": " + e.getMessage()); + main.logger().warning("Could not apply BlockState at " + origin + ": " + e.getMessage()); + main.getDebugLogger().stack(e); } } } diff --git a/common/src/main/java/com/dfsek/terra/api/util/ReflectionUtil.java b/common/src/main/java/com/dfsek/terra/api/util/ReflectionUtil.java index 74ee5fecd..34c70dae9 100644 --- a/common/src/main/java/com/dfsek/terra/api/util/ReflectionUtil.java +++ b/common/src/main/java/com/dfsek/terra/api/util/ReflectionUtil.java @@ -2,9 +2,12 @@ package com.dfsek.terra.api.util; import org.jetbrains.annotations.NotNull; +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; +import java.util.function.Consumer; import java.util.stream.Stream; public class ReflectionUtil { @@ -25,4 +28,9 @@ public class ReflectionUtil { } return result; } + + public static void ifAnnotationPresent(AnnotatedElement element, Class annotation, Consumer operation) { + T a = element.getAnnotation(annotation); + if(a != null) operation.accept(a); + } } diff --git a/common/src/main/java/com/dfsek/terra/api/util/collections/MaterialSet.java b/common/src/main/java/com/dfsek/terra/api/util/collections/MaterialSet.java new file mode 100644 index 000000000..77099137e --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/util/collections/MaterialSet.java @@ -0,0 +1,37 @@ +package com.dfsek.terra.api.util.collections; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockType; + +import java.util.Arrays; +import java.util.HashSet; + +public class MaterialSet extends HashSet { + private static final long serialVersionUID = 3056512763631017301L; + + public static MaterialSet singleton(BlockType material) { + MaterialSet set = new MaterialSet(); + set.add(material); + return set; + } + + public static MaterialSet get(BlockType... materials) { + MaterialSet set = new MaterialSet(); + set.addAll(Arrays.asList(materials)); + return set; + } + + public static MaterialSet get(BlockData... materials) { + MaterialSet set = new MaterialSet(); + Arrays.stream(materials).forEach(set::add); + return set; + } + + public static MaterialSet empty() { + return new MaterialSet(); + } + + private void add(BlockData data) { + add(data.getBlockType()); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/util/collections/ProbabilityCollection.java b/common/src/main/java/com/dfsek/terra/api/util/collections/ProbabilityCollection.java new file mode 100644 index 000000000..f9ec64992 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/util/collections/ProbabilityCollection.java @@ -0,0 +1,207 @@ +package com.dfsek.terra.api.util.collections; + +import com.dfsek.terra.api.math.MathUtil; +import com.dfsek.terra.api.math.noise.NoiseSampler; +import com.dfsek.terra.api.util.mutable.MutableInteger; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.function.Function; + +@SuppressWarnings("unchecked") +public class ProbabilityCollection implements Collection { + protected final Map cont = new HashMap<>(); + private Object[] array = new Object[0]; + private int size; + + public ProbabilityCollection add(E item, int probability) { + if(!cont.containsKey(item)) size++; + cont.computeIfAbsent(item, i -> new MutableInteger(0)).increment(); + int oldLength = array.length; + Object[] newArray = new Object[array.length + probability]; + System.arraycopy(array, 0, newArray, 0, array.length); // Expand array. + array = newArray; + for(int i = oldLength; i < array.length; i++) array[i] = item; + return this; + } + + public E get(Random r) { + if(array.length == 0) return null; + return (E) array[r.nextInt(array.length)]; + } + + public E get(NoiseSampler n, double x, double y, double z) { + if(array.length == 0) return null; + return (E) array[MathUtil.normalizeIndex(n.getNoise(x, y, z), array.length)]; + } + + public E get(NoiseSampler n, double x, double z) { + if(array.length == 0) return null; + return (E) array[MathUtil.normalizeIndex(n.getNoise(x, z), array.length)]; + } + + public ProbabilityCollection map(Function mapper, boolean carryNull) { + ProbabilityCollection newCollection = new ProbabilityCollection<>(); + newCollection.array = new Object[array.length]; + + for(int i = 0; i < array.length; i++) { + if(carryNull && array[i] == null) continue; + newCollection.array[i] = mapper.apply((E) array[i]); + } + return newCollection; + } + + public int getTotalProbability() { + return array.length; + } + + public int getProbability(E item) { + MutableInteger integer = cont.get(item); + return integer == null ? 0 : integer.get(); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("["); + + cont.forEach((item, prob) -> builder.append(item).append(": ").append(prob).append(", ")); + + return builder.append("]").toString(); + } + + @Override + public int size() { + return size; + } + + @Override + public boolean isEmpty() { + return array.length == 0; + } + + @Override + public boolean contains(Object o) { + return cont.containsKey(o); + } + + @NotNull + @Override + public Iterator iterator() { + return cont.keySet().iterator(); + } + + @NotNull + @Override + public Object[] toArray() { + return cont.keySet().toArray(); + } + + @SuppressWarnings("SuspiciousToArrayCall") + @NotNull + @Override + public T[] toArray(@NotNull T[] a) { + return cont.keySet().toArray(a); + } + + /** + * Adds an item with probability of 1. + */ + @Override + public boolean add(E e) { + add(e, 1); + return true; // Since this adds the item with a probability, the collection will always have changed. + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException("Cannot remove item from ProbabilityCollection!"); + } + + @Override + public boolean containsAll(@NotNull Collection c) { + return cont.keySet().containsAll(c); + } + + @Override + public boolean addAll(@NotNull Collection c) { + c.forEach(this::add); + return true; + } + + @Override + public boolean removeAll(@NotNull Collection c) { + throw new UnsupportedOperationException("Cannot remove item from ProbabilityCollection!"); + } + + @Override + public boolean retainAll(@NotNull Collection c) { + throw new UnsupportedOperationException("Cannot remove item from ProbabilityCollection!"); + } + + @Override + public void clear() { + cont.clear(); + array = new Object[0]; + } + + public Set getContents() { + return new HashSet<>(cont.keySet()); + } + + public static final class Singleton extends ProbabilityCollection { + private final T single; + + public Singleton(T single) { + this.single = single; + cont.put(single, new MutableInteger(1)); + } + + @Override + public ProbabilityCollection add(T item, int probability) { + throw new UnsupportedOperationException(); + } + + @Override + public ProbabilityCollection map(Function mapper, boolean carryNull) { + if(carryNull && single == null) return new Singleton<>(null); + return new Singleton<>(mapper.apply(single)); + } + + @Override + public T get(Random r) { + return single; + } + + @Override + public T get(NoiseSampler n, double x, double y, double z) { + return single; + } + + @Override + public T get(NoiseSampler n, double x, double z) { + return single; + } + + @Override + public int getTotalProbability() { + return 1; + } + + @Override + public int size() { + return 1; + } + + @Override + public Set getContents() { + return Collections.singleton(single); + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/util/generic/either/Either.java b/common/src/main/java/com/dfsek/terra/api/util/generic/either/Either.java new file mode 100644 index 000000000..cad5d93bf --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/util/generic/either/Either.java @@ -0,0 +1,52 @@ +package com.dfsek.terra.api.util.generic.either; + +import java.util.Optional; +import java.util.function.Consumer; + +public final class Either { + private final L left; + private final R right; + private final boolean leftPresent; + + private Either(L left, R right, boolean leftPresent) { + this.left = left; + this.right = right; + this.leftPresent = leftPresent; + } + + public static Either left(L1 left) { + return new Either<>(left, null, true); + } + + public static Either right(R1 right) { + return new Either<>(null, right, false); + } + + public Optional getLeft() { + if(leftPresent) return Optional.of(left); + return Optional.empty(); + } + + public Optional getRight() { + if(!leftPresent) return Optional.of(right); + return Optional.empty(); + } + + public Either ifLeft(Consumer action) { + if(leftPresent) action.accept(left); + return this; + } + + public Either ifRight(Consumer action) { + if(!leftPresent) action.accept(right); + return this; + } + + public boolean hasLeft() { + return leftPresent; + } + + public boolean hasRight() { + return !leftPresent; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/util/generic/pair/ImmutablePair.java b/common/src/main/java/com/dfsek/terra/api/util/generic/pair/ImmutablePair.java new file mode 100644 index 000000000..f58cbb52b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/util/generic/pair/ImmutablePair.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.api.util.generic.pair; + +public class ImmutablePair { + private final L left; + private final R right; + + public ImmutablePair(L left, R right) { + this.left = left; + this.right = right; + } + + public static ImmutablePair of(L1 left, R1 right) { + return new ImmutablePair<>(left, right); + } + + public R getRight() { + return right; + } + + public L getLeft() { + return left; + } + + public Pair mutable() { + return new Pair<>(left, right); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java b/common/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java new file mode 100644 index 000000000..dcb0be070 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java @@ -0,0 +1,35 @@ +package com.dfsek.terra.api.util.generic.pair; + +public class Pair { + private L left; + private R right; + + public Pair(L left, R right) { + this.left = left; + this.right = right; + } + + public static Pair of(L1 left, R1 right) { + return new Pair<>(left, right); + } + + public L getLeft() { + return left; + } + + public void setLeft(L left) { + this.left = left; + } + + public R getRight() { + return right; + } + + public void setRight(R right) { + this.right = right; + } + + public ImmutablePair immutable() { + return new ImmutablePair<>(left, right); + } +} diff --git a/common/src/main/java/com/dfsek/terra/util/hash/HashIntrinsic.java b/common/src/main/java/com/dfsek/terra/api/util/hash/HashIntrinsic.java similarity index 99% rename from common/src/main/java/com/dfsek/terra/util/hash/HashIntrinsic.java rename to common/src/main/java/com/dfsek/terra/api/util/hash/HashIntrinsic.java index 74166a7a8..638d8a66c 100644 --- a/common/src/main/java/com/dfsek/terra/util/hash/HashIntrinsic.java +++ b/common/src/main/java/com/dfsek/terra/api/util/hash/HashIntrinsic.java @@ -31,7 +31,7 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.dfsek.terra.util.hash; +package com.dfsek.terra.api.util.hash; import java.io.Serializable; diff --git a/common/src/main/java/com/dfsek/terra/util/hash/HashMapDoubleDouble.java b/common/src/main/java/com/dfsek/terra/api/util/hash/HashMapDoubleDouble.java similarity index 99% rename from common/src/main/java/com/dfsek/terra/util/hash/HashMapDoubleDouble.java rename to common/src/main/java/com/dfsek/terra/api/util/hash/HashMapDoubleDouble.java index 7ea6f735a..edad7aa32 100644 --- a/common/src/main/java/com/dfsek/terra/util/hash/HashMapDoubleDouble.java +++ b/common/src/main/java/com/dfsek/terra/api/util/hash/HashMapDoubleDouble.java @@ -31,7 +31,7 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.dfsek.terra.util.hash; +package com.dfsek.terra.api.util.hash; import java.io.Serializable; import java.util.NoSuchElementException; diff --git a/common/src/main/java/com/dfsek/terra/debug/DebugLogger.java b/common/src/main/java/com/dfsek/terra/api/util/logging/DebugLogger.java similarity index 91% rename from common/src/main/java/com/dfsek/terra/debug/DebugLogger.java rename to common/src/main/java/com/dfsek/terra/api/util/logging/DebugLogger.java index c907fab9f..5236401f9 100644 --- a/common/src/main/java/com/dfsek/terra/debug/DebugLogger.java +++ b/common/src/main/java/com/dfsek/terra/api/util/logging/DebugLogger.java @@ -1,6 +1,4 @@ -package com.dfsek.terra.debug; - -import java.util.logging.Logger; +package com.dfsek.terra.api.util.logging; public class DebugLogger { private final Logger logger; diff --git a/common/src/main/java/com/dfsek/terra/api/util/logging/JavaLogger.java b/common/src/main/java/com/dfsek/terra/api/util/logging/JavaLogger.java new file mode 100644 index 000000000..8a8a62e56 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/util/logging/JavaLogger.java @@ -0,0 +1,24 @@ +package com.dfsek.terra.api.util.logging; + +public class JavaLogger implements Logger { + private final java.util.logging.Logger logger; + + public JavaLogger(java.util.logging.Logger logger) { + this.logger = logger; + } + + @Override + public void info(String message) { + logger.info(message); + } + + @Override + public void warning(String message) { + logger.warning(message); + } + + @Override + public void severe(String message) { + logger.severe(message); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/util/logging/Logger.java b/common/src/main/java/com/dfsek/terra/api/util/logging/Logger.java new file mode 100644 index 000000000..df812533f --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/util/logging/Logger.java @@ -0,0 +1,9 @@ +package com.dfsek.terra.api.util.logging; + +public interface Logger { + void info(String message); + + void warning(String message); + + void severe(String message); +} diff --git a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableBoolean.java b/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableBoolean.java index 146bc606a..50abd8feb 100644 --- a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableBoolean.java +++ b/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableBoolean.java @@ -1,5 +1,7 @@ package com.dfsek.terra.api.util.mutable; +import org.jetbrains.annotations.NotNull; + public class MutableBoolean implements MutablePrimitive { private boolean value; @@ -17,4 +19,9 @@ public class MutableBoolean implements MutablePrimitive { value = !value; return value; } + + @Override + public int compareTo(@NotNull Boolean o) { + return Boolean.compare(value, o); + } } diff --git a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableDouble.java b/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableDouble.java index 483fa3d3e..be86110b3 100644 --- a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableDouble.java +++ b/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableDouble.java @@ -1,5 +1,7 @@ package com.dfsek.terra.api.util.mutable; +import org.jetbrains.annotations.NotNull; + public class MutableDouble extends MutableNumber { private static final long serialVersionUID = -2218110876763640053L; @@ -36,4 +38,9 @@ public class MutableDouble extends MutableNumber { public void divide(Double divide) { value /= divide; } + + @Override + public int compareTo(@NotNull Double o) { + return Double.compare(value, o); + } } diff --git a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableInteger.java b/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableInteger.java index 0774680d5..a2d949d87 100644 --- a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableInteger.java +++ b/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableInteger.java @@ -1,5 +1,7 @@ package com.dfsek.terra.api.util.mutable; +import org.jetbrains.annotations.NotNull; + public class MutableInteger extends MutableNumber { private static final long serialVersionUID = -4427935901819632745L; @@ -38,4 +40,9 @@ public class MutableInteger extends MutableNumber { public void add(int add) { value += add; } + + @Override + public int compareTo(@NotNull Integer o) { + return Integer.compare(value, o); + } } diff --git a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutablePrimitive.java b/common/src/main/java/com/dfsek/terra/api/util/mutable/MutablePrimitive.java index f1848007d..ab3e17f70 100644 --- a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutablePrimitive.java +++ b/common/src/main/java/com/dfsek/terra/api/util/mutable/MutablePrimitive.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.util.mutable; -public interface MutablePrimitive { +public interface MutablePrimitive extends Comparable{ T get(); void set(T value); diff --git a/common/src/main/java/com/dfsek/terra/api/util/mutable/package-info.java b/common/src/main/java/com/dfsek/terra/api/util/mutable/package-info.java new file mode 100644 index 000000000..02bf8235e --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/util/mutable/package-info.java @@ -0,0 +1,4 @@ +/** + * Mutable objects containing primitive types. + */ +package com.dfsek.terra.api.util.mutable; \ No newline at end of file diff --git a/common/src/main/java/com/dfsek/terra/api/util/seeded/SeededBuilder.java b/common/src/main/java/com/dfsek/terra/api/util/seeded/SeededBuilder.java index ff35cc1f5..1a7d15d39 100644 --- a/common/src/main/java/com/dfsek/terra/api/util/seeded/SeededBuilder.java +++ b/common/src/main/java/com/dfsek/terra/api/util/seeded/SeededBuilder.java @@ -2,6 +2,7 @@ package com.dfsek.terra.api.util.seeded; import java.util.function.Function; +@FunctionalInterface public interface SeededBuilder extends Function { } diff --git a/common/src/main/java/com/dfsek/terra/api/util/seeded/SourceSeeded.java b/common/src/main/java/com/dfsek/terra/api/util/seeded/SourceSeeded.java index e2a9e0e3c..5ec6f4511 100644 --- a/common/src/main/java/com/dfsek/terra/api/util/seeded/SourceSeeded.java +++ b/common/src/main/java/com/dfsek/terra/api/util/seeded/SourceSeeded.java @@ -1,6 +1,7 @@ package com.dfsek.terra.api.util.seeded; -import com.dfsek.terra.biome.pipeline.source.BiomeSource; +import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource; +@FunctionalInterface public interface SourceSeeded extends SeededBuilder { } diff --git a/common/src/main/java/com/dfsek/terra/api/util/seeded/StageSeeded.java b/common/src/main/java/com/dfsek/terra/api/util/seeded/StageSeeded.java index c9754c22f..02ebbe181 100644 --- a/common/src/main/java/com/dfsek/terra/api/util/seeded/StageSeeded.java +++ b/common/src/main/java/com/dfsek/terra/api/util/seeded/StageSeeded.java @@ -1,6 +1,7 @@ package com.dfsek.terra.api.util.seeded; -import com.dfsek.terra.biome.pipeline.stages.Stage; +import com.dfsek.terra.api.world.biome.pipeline.stages.Stage; +@FunctionalInterface public interface StageSeeded extends SeededBuilder { } diff --git a/common/src/main/java/com/dfsek/terra/util/PaletteUtil.java b/common/src/main/java/com/dfsek/terra/api/util/world/PaletteUtil.java similarity index 86% rename from common/src/main/java/com/dfsek/terra/util/PaletteUtil.java rename to common/src/main/java/com/dfsek/terra/api/util/world/PaletteUtil.java index 77478effd..69edf202e 100644 --- a/common/src/main/java/com/dfsek/terra/util/PaletteUtil.java +++ b/common/src/main/java/com/dfsek/terra/api/util/world/PaletteUtil.java @@ -1,11 +1,11 @@ -package com.dfsek.terra.util; +package com.dfsek.terra.api.util.world; import com.dfsek.terra.api.math.MathUtil; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.palette.holder.PaletteHolder; import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.world.generation.math.Sampler; +import com.dfsek.terra.world.generation.math.samplers.Sampler; public final class PaletteUtil { public static Palette getPalette(int x, int y, int z, BiomeTemplate c, Sampler sampler) { diff --git a/common/src/main/java/com/dfsek/terra/util/PopulationUtil.java b/common/src/main/java/com/dfsek/terra/api/util/world/PopulationUtil.java similarity index 91% rename from common/src/main/java/com/dfsek/terra/util/PopulationUtil.java rename to common/src/main/java/com/dfsek/terra/api/util/world/PopulationUtil.java index b260ae451..a1805d437 100644 --- a/common/src/main/java/com/dfsek/terra/util/PopulationUtil.java +++ b/common/src/main/java/com/dfsek/terra/api/util/world/PopulationUtil.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.util; +package com.dfsek.terra.api.util.world; import com.dfsek.terra.api.math.MathUtil; import com.dfsek.terra.api.platform.world.Chunk; diff --git a/common/src/main/java/com/dfsek/terra/biome/TerraBiome.java b/common/src/main/java/com/dfsek/terra/api/world/biome/TerraBiome.java similarity index 82% rename from common/src/main/java/com/dfsek/terra/biome/TerraBiome.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/TerraBiome.java index 7bcb917de..4aaac0e9e 100644 --- a/common/src/main/java/com/dfsek/terra/biome/TerraBiome.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/TerraBiome.java @@ -1,10 +1,9 @@ -package com.dfsek.terra.biome; +package com.dfsek.terra.api.world.biome; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.platform.world.Biome; import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.world.biome.Generator; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import java.util.Set; diff --git a/common/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java b/common/src/main/java/com/dfsek/terra/api/world/biome/UserDefinedBiome.java similarity index 75% rename from common/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/UserDefinedBiome.java index 99d768482..b6e5d9570 100644 --- a/common/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/UserDefinedBiome.java @@ -1,20 +1,18 @@ -package com.dfsek.terra.biome; +package com.dfsek.terra.api.world.biome; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.platform.world.Biome; import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.world.biome.Generator; -import com.dfsek.terra.config.builder.GeneratorBuilder; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.config.templates.BiomeTemplate; +import com.dfsek.terra.world.generation.WorldGenerator; -import java.util.HashSet; import java.util.Set; /** * Class representing a config-defined biome */ public class UserDefinedBiome implements TerraBiome { - private final GeneratorBuilder gen; + private final WorldGenerator gen; private final ProbabilityCollection vanilla; private final String id; private final BiomeTemplate config; @@ -22,13 +20,13 @@ public class UserDefinedBiome implements TerraBiome { private final Set tags; - public UserDefinedBiome(ProbabilityCollection vanilla, GeneratorBuilder gen, BiomeTemplate config) { + public UserDefinedBiome(ProbabilityCollection vanilla, WorldGenerator gen, BiomeTemplate config) { this.vanilla = vanilla; this.gen = gen; this.id = config.getID(); this.config = config; this.color = config.getColor(); - this.tags = config.getTags() == null ? new HashSet<>() : config.getTags(); + this.tags = config.getTags(); tags.add("BIOME:" + id); } @@ -53,7 +51,7 @@ public class UserDefinedBiome implements TerraBiome { @Override public Generator getGenerator(World w) { - return gen.build(w.getSeed()); + return gen; } @Override @@ -65,4 +63,9 @@ public class UserDefinedBiome implements TerraBiome { public Set getTags() { return tags; } + + @Override + public String toString() { + return "{BIOME:" + getID() + "}"; + } } diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/BiomeHolder.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/BiomeHolder.java new file mode 100644 index 000000000..46edff4c4 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/BiomeHolder.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.api.world.biome.pipeline; + +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.pipeline.expand.BiomeExpander; +import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; +import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource; + +public interface BiomeHolder { + BiomeHolder expand(BiomeExpander expander); + + void mutate(BiomeMutator mutator); + + void fill(BiomeSource source); + + TerraBiome getBiome(int x, int z); + + TerraBiome getBiomeRaw(int x, int z); +} diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/BiomePipeline.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/BiomePipeline.java similarity index 91% rename from common/src/main/java/com/dfsek/terra/biome/pipeline/BiomePipeline.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/BiomePipeline.java index a2bcb5df5..ed4211892 100644 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/BiomePipeline.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/BiomePipeline.java @@ -1,10 +1,10 @@ -package com.dfsek.terra.biome.pipeline; +package com.dfsek.terra.api.world.biome.pipeline; import com.dfsek.terra.api.math.vector.Vector2; import com.dfsek.terra.api.util.GlueList; import com.dfsek.terra.api.util.seeded.StageSeeded; -import com.dfsek.terra.biome.pipeline.source.BiomeSource; -import com.dfsek.terra.biome.pipeline.stages.Stage; +import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource; +import com.dfsek.terra.api.world.biome.pipeline.stages.Stage; import java.util.List; import java.util.stream.Collectors; diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/TerraBiomeHolder.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/TerraBiomeHolder.java similarity index 89% rename from common/src/main/java/com/dfsek/terra/biome/pipeline/TerraBiomeHolder.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/TerraBiomeHolder.java index 9a44a8935..df07577c0 100644 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/TerraBiomeHolder.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/TerraBiomeHolder.java @@ -1,10 +1,10 @@ -package com.dfsek.terra.biome.pipeline; +package com.dfsek.terra.api.world.biome.pipeline; import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.pipeline.expand.BiomeExpander; -import com.dfsek.terra.biome.pipeline.mutator.BiomeMutator; -import com.dfsek.terra.biome.pipeline.source.BiomeSource; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.pipeline.expand.BiomeExpander; +import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; +import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource; public class TerraBiomeHolder implements BiomeHolder { private final Vector2 origin; diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/expand/BiomeExpander.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/expand/BiomeExpander.java new file mode 100644 index 000000000..15082a0fe --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/expand/BiomeExpander.java @@ -0,0 +1,7 @@ +package com.dfsek.terra.api.world.biome.pipeline.expand; + +import com.dfsek.terra.api.world.biome.TerraBiome; + +public interface BiomeExpander { + TerraBiome getBetween(double x, double z, TerraBiome... others); +} diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/expand/FractalExpander.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/expand/FractalExpander.java similarity index 81% rename from common/src/main/java/com/dfsek/terra/biome/pipeline/expand/FractalExpander.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/expand/FractalExpander.java index bba7b7931..a7d44be84 100644 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/expand/FractalExpander.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/expand/FractalExpander.java @@ -1,8 +1,8 @@ -package com.dfsek.terra.biome.pipeline.expand; +package com.dfsek.terra.api.world.biome.pipeline.expand; import com.dfsek.terra.api.math.MathUtil; import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.TerraBiome; public class FractalExpander implements BiomeExpander { private final NoiseSampler sampler; diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/BiomeMutator.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BiomeMutator.java similarity index 75% rename from common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/BiomeMutator.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BiomeMutator.java index 83cf9aa11..da70c3d9e 100644 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/BiomeMutator.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BiomeMutator.java @@ -1,7 +1,7 @@ -package com.dfsek.terra.biome.pipeline.mutator; +package com.dfsek.terra.api.world.biome.pipeline.mutator; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.pipeline.BiomeHolder; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.pipeline.BiomeHolder; public interface BiomeMutator { TerraBiome mutate(ViewPoint viewPoint, double x, double z); diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/BorderListMutator.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BorderListMutator.java similarity index 91% rename from common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/BorderListMutator.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BorderListMutator.java index cc5fdac47..d16016d91 100644 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/BorderListMutator.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BorderListMutator.java @@ -1,8 +1,8 @@ -package com.dfsek.terra.biome.pipeline.mutator; +package com.dfsek.terra.api.world.biome.pipeline.mutator; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.biome.TerraBiome; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; +import com.dfsek.terra.api.world.biome.TerraBiome; import java.util.Map; diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/BorderMutator.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BorderMutator.java similarity index 88% rename from common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/BorderMutator.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BorderMutator.java index c5add13f0..d6195c7a4 100644 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/BorderMutator.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BorderMutator.java @@ -1,8 +1,8 @@ -package com.dfsek.terra.biome.pipeline.mutator; +package com.dfsek.terra.api.world.biome.pipeline.mutator; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.biome.TerraBiome; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; +import com.dfsek.terra.api.world.biome.TerraBiome; public class BorderMutator implements BiomeMutator { private final String border; diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/ReplaceListMutator.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/ReplaceListMutator.java similarity index 87% rename from common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/ReplaceListMutator.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/ReplaceListMutator.java index 9a4e8de1e..8d701109a 100644 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/ReplaceListMutator.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/ReplaceListMutator.java @@ -1,8 +1,8 @@ -package com.dfsek.terra.biome.pipeline.mutator; +package com.dfsek.terra.api.world.biome.pipeline.mutator; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.biome.TerraBiome; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; +import com.dfsek.terra.api.world.biome.TerraBiome; import java.util.Map; diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/ReplaceMutator.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/ReplaceMutator.java similarity index 82% rename from common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/ReplaceMutator.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/ReplaceMutator.java index 8cad6a777..7bc705b66 100644 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/ReplaceMutator.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/ReplaceMutator.java @@ -1,8 +1,8 @@ -package com.dfsek.terra.biome.pipeline.mutator; +package com.dfsek.terra.api.world.biome.pipeline.mutator; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.biome.TerraBiome; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; +import com.dfsek.terra.api.world.biome.TerraBiome; public class ReplaceMutator implements BiomeMutator { private final String replaceableTag; diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/SmoothMutator.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/SmoothMutator.java similarity index 90% rename from common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/SmoothMutator.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/SmoothMutator.java index 490f791d0..a3c679ea1 100644 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/SmoothMutator.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/SmoothMutator.java @@ -1,8 +1,8 @@ -package com.dfsek.terra.biome.pipeline.mutator; +package com.dfsek.terra.api.world.biome.pipeline.mutator; import com.dfsek.terra.api.math.MathUtil; import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.TerraBiome; import java.util.Objects; diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/source/BiomeSource.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/source/BiomeSource.java new file mode 100644 index 000000000..b2e2e37cc --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/source/BiomeSource.java @@ -0,0 +1,11 @@ +package com.dfsek.terra.api.world.biome.pipeline.source; + +import com.dfsek.terra.api.world.biome.TerraBiome; + +public interface BiomeSource { + TerraBiome getBiome(double x, double z); + + enum Type { + NOISE + } +} diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/source/RandomSource.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/source/RandomSource.java similarity index 73% rename from common/src/main/java/com/dfsek/terra/biome/pipeline/source/RandomSource.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/source/RandomSource.java index e1a487e32..fa95986b4 100644 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/source/RandomSource.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/source/RandomSource.java @@ -1,8 +1,8 @@ -package com.dfsek.terra.biome.pipeline.source; +package com.dfsek.terra.api.world.biome.pipeline.source; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.biome.TerraBiome; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; +import com.dfsek.terra.api.world.biome.TerraBiome; public class RandomSource implements BiomeSource { private final ProbabilityCollection biomes; diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/stages/ExpanderStage.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/ExpanderStage.java similarity index 68% rename from common/src/main/java/com/dfsek/terra/biome/pipeline/stages/ExpanderStage.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/ExpanderStage.java index b8f26bf6c..fc0555e19 100644 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/stages/ExpanderStage.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/ExpanderStage.java @@ -1,7 +1,7 @@ -package com.dfsek.terra.biome.pipeline.stages; +package com.dfsek.terra.api.world.biome.pipeline.stages; -import com.dfsek.terra.biome.pipeline.BiomeHolder; -import com.dfsek.terra.biome.pipeline.expand.BiomeExpander; +import com.dfsek.terra.api.world.biome.pipeline.BiomeHolder; +import com.dfsek.terra.api.world.biome.pipeline.expand.BiomeExpander; public class ExpanderStage implements Stage { private final BiomeExpander expander; diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/stages/MutatorStage.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/MutatorStage.java similarity index 70% rename from common/src/main/java/com/dfsek/terra/biome/pipeline/stages/MutatorStage.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/MutatorStage.java index dab5b5f12..a9b060fd1 100644 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/stages/MutatorStage.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/MutatorStage.java @@ -1,7 +1,7 @@ -package com.dfsek.terra.biome.pipeline.stages; +package com.dfsek.terra.api.world.biome.pipeline.stages; -import com.dfsek.terra.biome.pipeline.BiomeHolder; -import com.dfsek.terra.biome.pipeline.mutator.BiomeMutator; +import com.dfsek.terra.api.world.biome.pipeline.BiomeHolder; +import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; public class MutatorStage implements Stage { private final BiomeMutator mutator; diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/Stage.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/Stage.java new file mode 100644 index 000000000..a179da2eb --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/Stage.java @@ -0,0 +1,10 @@ +package com.dfsek.terra.api.world.biome.pipeline.stages; + +import com.dfsek.terra.api.world.biome.pipeline.BiomeHolder; + +public interface Stage { + boolean isExpansion(); + + BiomeHolder apply(BiomeHolder in); + +} diff --git a/common/src/main/java/com/dfsek/terra/biome/provider/BiomeProvider.java b/common/src/main/java/com/dfsek/terra/api/world/biome/provider/BiomeProvider.java similarity index 87% rename from common/src/main/java/com/dfsek/terra/biome/provider/BiomeProvider.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/provider/BiomeProvider.java index 9041edd85..c1f664314 100644 --- a/common/src/main/java/com/dfsek/terra/biome/provider/BiomeProvider.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/provider/BiomeProvider.java @@ -1,9 +1,9 @@ -package com.dfsek.terra.biome.provider; +package com.dfsek.terra.api.world.biome.provider; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Vector2; import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.TerraBiome; public interface BiomeProvider { TerraBiome getBiome(int x, int z); diff --git a/common/src/main/java/com/dfsek/terra/biome/provider/ImageBiomeProvider.java b/common/src/main/java/com/dfsek/terra/api/world/biome/provider/ImageBiomeProvider.java similarity index 86% rename from common/src/main/java/com/dfsek/terra/biome/provider/ImageBiomeProvider.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/provider/ImageBiomeProvider.java index 2f2a6467e..5e210abc7 100644 --- a/common/src/main/java/com/dfsek/terra/biome/provider/ImageBiomeProvider.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/provider/ImageBiomeProvider.java @@ -1,13 +1,15 @@ -package com.dfsek.terra.biome.provider; +package com.dfsek.terra.api.world.biome.provider; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.registry.TerraRegistry; +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.registry.OpenRegistry; import net.jafama.FastMath; import java.awt.*; import java.awt.image.BufferedImage; import java.util.HashMap; import java.util.Map; +import java.util.Set; public class ImageBiomeProvider implements BiomeProvider, BiomeProvider.BiomeProviderBuilder { // This provider does not need a seed, so it is its own builder. private final Map colorBiomeMap = new HashMap<>(); @@ -15,7 +17,7 @@ public class ImageBiomeProvider implements BiomeProvider, BiomeProvider.BiomePro private final int resolution; private final Align align; - public ImageBiomeProvider(TerraRegistry registry, BufferedImage image, int resolution, Align align) { + public ImageBiomeProvider(Set registry, BufferedImage image, int resolution, Align align) { this.image = image; this.resolution = resolution; this.align = align; diff --git a/common/src/main/java/com/dfsek/terra/biome/provider/SingleBiomeProvider.java b/common/src/main/java/com/dfsek/terra/api/world/biome/provider/SingleBiomeProvider.java similarity index 79% rename from common/src/main/java/com/dfsek/terra/biome/provider/SingleBiomeProvider.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/provider/SingleBiomeProvider.java index 1119788f6..6dc103cd6 100644 --- a/common/src/main/java/com/dfsek/terra/biome/provider/SingleBiomeProvider.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/provider/SingleBiomeProvider.java @@ -1,6 +1,6 @@ -package com.dfsek.terra.biome.provider; +package com.dfsek.terra.api.world.biome.provider; -import com.dfsek.terra.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.TerraBiome; public class SingleBiomeProvider implements BiomeProvider, BiomeProvider.BiomeProviderBuilder { private final TerraBiome biome; diff --git a/common/src/main/java/com/dfsek/terra/biome/provider/StandardBiomeProvider.java b/common/src/main/java/com/dfsek/terra/api/world/biome/provider/StandardBiomeProvider.java similarity index 88% rename from common/src/main/java/com/dfsek/terra/biome/provider/StandardBiomeProvider.java rename to common/src/main/java/com/dfsek/terra/api/world/biome/provider/StandardBiomeProvider.java index f54c3c287..397cbe7a4 100644 --- a/common/src/main/java/com/dfsek/terra/biome/provider/StandardBiomeProvider.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/provider/StandardBiomeProvider.java @@ -1,11 +1,11 @@ -package com.dfsek.terra.biome.provider; +package com.dfsek.terra.api.world.biome.provider; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.noise.NoiseSampler; import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.pipeline.BiomeHolder; -import com.dfsek.terra.biome.pipeline.BiomePipeline; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.pipeline.BiomeHolder; +import com.dfsek.terra.api.world.biome.pipeline.BiomePipeline; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; diff --git a/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java b/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java index c4b52f2f3..280ee8f96 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java +++ b/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java @@ -1,16 +1,19 @@ package com.dfsek.terra.api.world.generation; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.platform.world.BiomeGrid; import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.generator.ChunkData; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.world.generation.math.SamplerCache; +import com.dfsek.terra.world.generation.math.samplers.Sampler; import org.jetbrains.annotations.NotNull; import java.util.Random; public interface TerraChunkGenerator { - ChunkGenerator.ChunkData generateChunkData(@NotNull World world, Random random, int x, int z, ChunkGenerator.ChunkData original); + ChunkData generateChunkData(@NotNull World world, Random random, int x, int z, ChunkData original); void generateBiomes(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome); @@ -27,4 +30,6 @@ public interface TerraChunkGenerator { ConfigPack getConfigPack(); TerraPlugin getMain(); + + Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth); } diff --git a/common/src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java b/common/src/main/java/com/dfsek/terra/api/world/locate/AsyncBiomeFinder.java similarity index 85% rename from common/src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java rename to common/src/main/java/com/dfsek/terra/api/world/locate/AsyncBiomeFinder.java index 3fd723abb..c41892b12 100644 --- a/common/src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java +++ b/common/src/main/java/com/dfsek/terra/api/world/locate/AsyncBiomeFinder.java @@ -1,10 +1,10 @@ -package com.dfsek.terra.async; +package com.dfsek.terra.api.world.locate; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; diff --git a/common/src/main/java/com/dfsek/terra/async/AsyncFeatureFinder.java b/common/src/main/java/com/dfsek/terra/api/world/locate/AsyncFeatureFinder.java similarity index 94% rename from common/src/main/java/com/dfsek/terra/async/AsyncFeatureFinder.java rename to common/src/main/java/com/dfsek/terra/api/world/locate/AsyncFeatureFinder.java index 69869a861..31b2dec6b 100644 --- a/common/src/main/java/com/dfsek/terra/async/AsyncFeatureFinder.java +++ b/common/src/main/java/com/dfsek/terra/api/world/locate/AsyncFeatureFinder.java @@ -1,10 +1,10 @@ -package com.dfsek.terra.async; +package com.dfsek.terra.api.world.locate; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; diff --git a/common/src/main/java/com/dfsek/terra/async/AsyncStructureFinder.java b/common/src/main/java/com/dfsek/terra/api/world/locate/AsyncStructureFinder.java similarity index 89% rename from common/src/main/java/com/dfsek/terra/async/AsyncStructureFinder.java rename to common/src/main/java/com/dfsek/terra/api/world/locate/AsyncStructureFinder.java index 89aa90344..2686fb2db 100644 --- a/common/src/main/java/com/dfsek/terra/async/AsyncStructureFinder.java +++ b/common/src/main/java/com/dfsek/terra/api/world/locate/AsyncStructureFinder.java @@ -1,13 +1,13 @@ -package com.dfsek.terra.async; +package com.dfsek.terra.api.world.locate; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.MathUtil; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.structures.structure.Rotation; import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.world.population.items.TerraStructure; import net.jafama.FastMath; import org.jetbrains.annotations.NotNull; diff --git a/common/src/main/java/com/dfsek/terra/api/world/palette/Palette.java b/common/src/main/java/com/dfsek/terra/api/world/palette/Palette.java index 0ea01239a..881cd406c 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/palette/Palette.java +++ b/common/src/main/java/com/dfsek/terra/api/world/palette/Palette.java @@ -1,8 +1,8 @@ package com.dfsek.terra.api.world.palette; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.noise.NoiseSampler; import com.dfsek.terra.api.util.GlueList; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import java.util.List; import java.util.Random; diff --git a/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteLayerHolder.java b/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteLayerHolder.java index 8881b1646..cb44e8fb4 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteLayerHolder.java +++ b/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteLayerHolder.java @@ -1,8 +1,8 @@ package com.dfsek.terra.api.world.palette.holder; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.noise.NoiseSampler; import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import org.jetbrains.annotations.NotNull; public class PaletteLayerHolder { diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/Tree.java b/common/src/main/java/com/dfsek/terra/api/world/tree/Tree.java index 47221fd20..0e14dd176 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/tree/Tree.java +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/Tree.java @@ -2,13 +2,12 @@ package com.dfsek.terra.api.world.tree; import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.util.collections.MaterialSet; import java.util.Random; -import java.util.Set; public interface Tree { boolean plant(Location l, Random r); - Set getSpawnable(); + MaterialSet getSpawnable(); } diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/FractalTree.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/FractalTree.java index 639fd7774..9a95e3d8c 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/FractalTree.java +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/FractalTree.java @@ -1,11 +1,11 @@ package com.dfsek.terra.api.world.tree.fractal; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.entity.Entity; import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.util.MaterialSet; +import com.dfsek.terra.api.util.collections.MaterialSet; import java.util.Random; import java.util.function.Consumer; diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/TreeGeometry.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/TreeGeometry.java index 7ec3ee28c..46fc1f716 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/TreeGeometry.java +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/TreeGeometry.java @@ -1,9 +1,9 @@ package com.dfsek.terra.api.world.tree.fractal; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import java.util.Random; diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/Cactus.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/Cactus.java index d3b5fd463..ef5f29197 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/Cactus.java +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/Cactus.java @@ -1,18 +1,18 @@ package com.dfsek.terra.api.world.tree.fractal.trees; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.world.tree.fractal.FractalTree; -import com.dfsek.terra.util.MaterialSet; import java.util.Random; public class Cactus extends FractalTree { @Override public MaterialSet getSpawnable() { - return MaterialSet.get(main.getWorldHandle().createMaterialData("minecraft:sand"), - main.getWorldHandle().createMaterialData("minecraft:red_sand")); + return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:sand"), + main.getWorldHandle().createBlockData("minecraft:red_sand")); } diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/IceSpike.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/IceSpike.java index 5dbe76690..716313df4 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/IceSpike.java +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/IceSpike.java @@ -1,14 +1,14 @@ package com.dfsek.terra.api.world.tree.fractal.trees; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.util.collections.MaterialSet; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.world.tree.fractal.FractalTree; import com.dfsek.terra.api.world.tree.fractal.TreeGeometry; -import com.dfsek.terra.util.MaterialSet; import java.util.Random; @@ -19,10 +19,10 @@ public class IceSpike extends FractalTree { @Override public MaterialSet getSpawnable() { - return MaterialSet.get(main.getWorldHandle().createMaterialData("minecraft:stone"), - main.getWorldHandle().createMaterialData("minecraft:gravel"), - main.getWorldHandle().createMaterialData("minecraft:snow_block"), - main.getWorldHandle().createMaterialData("minecraft:grass_block")); + return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:stone"), + main.getWorldHandle().createBlockData("minecraft:gravel"), + main.getWorldHandle().createBlockData("minecraft:snow_block"), + main.getWorldHandle().createBlockData("minecraft:grass_block")); } /** diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/OakTree.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/OakTree.java index de8ad123b..c973d872a 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/OakTree.java +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/OakTree.java @@ -1,12 +1,12 @@ package com.dfsek.terra.api.world.tree.fractal.trees; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.world.tree.fractal.FractalTree; import com.dfsek.terra.api.world.tree.fractal.TreeGeometry; -import com.dfsek.terra.util.MaterialSet; import net.jafama.FastMath; import java.util.Random; @@ -17,8 +17,8 @@ public class OakTree extends FractalTree { @Override public MaterialSet getSpawnable() { - return MaterialSet.get(main.getWorldHandle().createMaterialData("minecraft:podzol"), - main.getWorldHandle().createMaterialData("minecraft:grass_block")); + return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:podzol"), + main.getWorldHandle().createBlockData("minecraft:grass_block")); } /** @@ -39,7 +39,7 @@ public class OakTree extends FractalTree { private void growBranch(Location l1, Vector3 diff, double d1, int recursions, Random r) { BlockData wood = getMain().getWorldHandle().createBlockData("minecraft:oak_wood"); - BlockData leaves = getMain().getWorldHandle().createBlockData("minecraft:oak_leave"); + BlockData leaves = getMain().getWorldHandle().createBlockData("minecraft:oak_leaves"); if(recursions > 1) { geo.generateSphere(l1, leaves, 1 + r.nextInt(2) + (3 - recursions), false, r); if(recursions > 2) return; diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/ShatteredPillar.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/ShatteredPillar.java index ed66b3d68..35c24bff6 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/ShatteredPillar.java +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/ShatteredPillar.java @@ -1,10 +1,10 @@ package com.dfsek.terra.api.world.tree.fractal.trees; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.world.tree.fractal.FractalTree; -import com.dfsek.terra.util.MaterialSet; import java.util.Random; @@ -12,7 +12,7 @@ public class ShatteredPillar extends FractalTree { @Override public MaterialSet getSpawnable() { - return MaterialSet.get(main.getWorldHandle().createMaterialData("minecraft:end_stone")); + return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:end_stone")); } /** diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/ShatteredTree.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/ShatteredTree.java index 0841d5e2f..06dded13b 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/ShatteredTree.java +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/ShatteredTree.java @@ -1,14 +1,14 @@ package com.dfsek.terra.api.world.tree.fractal.trees; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.util.collections.MaterialSet; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.world.tree.fractal.FractalTree; import com.dfsek.terra.api.world.tree.fractal.TreeGeometry; -import com.dfsek.terra.util.MaterialSet; import net.jafama.FastMath; import java.util.Random; @@ -20,7 +20,7 @@ public class ShatteredTree extends FractalTree { @Override public MaterialSet getSpawnable() { - return MaterialSet.get(main.getWorldHandle().createMaterialData("minecraft:end_stone")); + return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:end_stone")); } /** diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SmallShatteredPillar.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SmallShatteredPillar.java index a06634e6d..35825e7fe 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SmallShatteredPillar.java +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SmallShatteredPillar.java @@ -1,10 +1,10 @@ package com.dfsek.terra.api.world.tree.fractal.trees; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.world.tree.fractal.FractalTree; -import com.dfsek.terra.util.MaterialSet; import java.util.Random; @@ -12,7 +12,7 @@ public class SmallShatteredPillar extends FractalTree { @Override public MaterialSet getSpawnable() { - return MaterialSet.get(main.getWorldHandle().createMaterialData("minecraft:end_stone")); + return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:end_stone")); } /** diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SmallShatteredTree.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SmallShatteredTree.java index c5094c61a..6148d78c4 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SmallShatteredTree.java +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SmallShatteredTree.java @@ -1,14 +1,14 @@ package com.dfsek.terra.api.world.tree.fractal.trees; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.util.collections.MaterialSet; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.world.tree.fractal.FractalTree; import com.dfsek.terra.api.world.tree.fractal.TreeGeometry; -import com.dfsek.terra.util.MaterialSet; import net.jafama.FastMath; import java.util.Random; @@ -20,7 +20,7 @@ public class SmallShatteredTree extends FractalTree { @Override public MaterialSet getSpawnable() { - return MaterialSet.get(main.getWorldHandle().createMaterialData("minecraft:end_stone")); + return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:end_stone")); } /** diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SpruceTree.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SpruceTree.java index 327c52706..d0db1dea9 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SpruceTree.java +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SpruceTree.java @@ -1,12 +1,12 @@ package com.dfsek.terra.api.world.tree.fractal.trees; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.world.tree.fractal.FractalTree; import com.dfsek.terra.api.world.tree.fractal.TreeGeometry; -import com.dfsek.terra.util.MaterialSet; import net.jafama.FastMath; import java.util.Random; @@ -16,8 +16,8 @@ public class SpruceTree extends FractalTree { @Override public MaterialSet getSpawnable() { - return MaterialSet.get(main.getWorldHandle().createMaterialData("minecraft:podzol"), - main.getWorldHandle().createMaterialData("minecraft:grass_block")); + return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:podzol"), + main.getWorldHandle().createBlockData("minecraft:grass_block")); } /** diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/BiomeHolder.java b/common/src/main/java/com/dfsek/terra/biome/pipeline/BiomeHolder.java deleted file mode 100644 index 7e2fb6bfb..000000000 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/BiomeHolder.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.biome.pipeline; - -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.pipeline.expand.BiomeExpander; -import com.dfsek.terra.biome.pipeline.mutator.BiomeMutator; -import com.dfsek.terra.biome.pipeline.source.BiomeSource; - -public interface BiomeHolder { - BiomeHolder expand(BiomeExpander expander); - - void mutate(BiomeMutator mutator); - - void fill(BiomeSource source); - - TerraBiome getBiome(int x, int z); - - TerraBiome getBiomeRaw(int x, int z); -} diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/expand/BiomeExpander.java b/common/src/main/java/com/dfsek/terra/biome/pipeline/expand/BiomeExpander.java deleted file mode 100644 index a3530ca70..000000000 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/expand/BiomeExpander.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.biome.pipeline.expand; - -import com.dfsek.terra.biome.TerraBiome; - -public interface BiomeExpander { - TerraBiome getBetween(double x, double z, TerraBiome... others); -} diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/source/BiomeSource.java b/common/src/main/java/com/dfsek/terra/biome/pipeline/source/BiomeSource.java deleted file mode 100644 index 80b0961c6..000000000 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/source/BiomeSource.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.biome.pipeline.source; - -import com.dfsek.terra.biome.TerraBiome; - -public interface BiomeSource { - TerraBiome getBiome(double x, double z); -} diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/stages/Stage.java b/common/src/main/java/com/dfsek/terra/biome/pipeline/stages/Stage.java deleted file mode 100644 index 531313363..000000000 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/stages/Stage.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dfsek.terra.biome.pipeline.stages; - -import com.dfsek.terra.biome.pipeline.BiomeHolder; - -public interface Stage { - boolean isExpansion(); - - BiomeHolder apply(BiomeHolder in); - -} diff --git a/common/src/main/java/com/dfsek/terra/carving/CarverCache.java b/common/src/main/java/com/dfsek/terra/carving/CarverCache.java index 75a645aa0..00d3427a1 100644 --- a/common/src/main/java/com/dfsek/terra/carving/CarverCache.java +++ b/common/src/main/java/com/dfsek/terra/carving/CarverCache.java @@ -1,15 +1,15 @@ package com.dfsek.terra.carving; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.MathUtil; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.util.FastRandom; import com.dfsek.terra.api.util.GlueList; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.api.world.carving.Worm; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.biome.provider.BiomeProvider; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; diff --git a/common/src/main/java/com/dfsek/terra/carving/CarverPalette.java b/common/src/main/java/com/dfsek/terra/carving/CarverPalette.java index 249c36957..a15d1710c 100644 --- a/common/src/main/java/com/dfsek/terra/carving/CarverPalette.java +++ b/common/src/main/java/com/dfsek/terra/carving/CarverPalette.java @@ -1,9 +1,9 @@ package com.dfsek.terra.carving; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; -import com.dfsek.terra.util.MaterialSet; +import com.dfsek.terra.api.platform.block.BlockType; +import com.dfsek.terra.api.util.collections.MaterialSet; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import java.util.Map; import java.util.TreeMap; @@ -29,7 +29,7 @@ public class CarverPalette { return layers[y]; } - public boolean canReplace(MaterialData material) { + public boolean canReplace(BlockType material) { return blacklist != replace.contains(material); } diff --git a/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java b/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java index 4c9a9a80a..79bd897a4 100644 --- a/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java +++ b/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java @@ -4,7 +4,7 @@ import com.dfsek.paralithic.Expression; import com.dfsek.paralithic.eval.parser.Parser; import com.dfsek.paralithic.eval.parser.Scope; import com.dfsek.paralithic.eval.tokenizer.ParseException; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.math.paralithic.defined.UserDefinedFunction; import com.dfsek.terra.api.math.paralithic.noise.NoiseFunction2; @@ -13,9 +13,9 @@ import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.util.FastRandom; import com.dfsek.terra.api.util.seeded.NoiseSeeded; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; import com.dfsek.terra.api.world.carving.Carver; import com.dfsek.terra.api.world.carving.Worm; -import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; import com.dfsek.terra.config.templates.BiomeTemplate; import com.dfsek.terra.config.templates.CarverTemplate; @@ -39,7 +39,7 @@ public class UserDefinedCarver extends Carver { private final Expression yRad; private final Expression zRad; - private final Map cacheMap = new ConcurrentHashMap<>(); + private final Map cacheMap = new ConcurrentHashMap<>(); private final TerraPlugin main; private double step = 2; private Range recalc = new Range(8, 10); @@ -108,7 +108,7 @@ public class UserDefinedCarver extends Carver { @Override public void carve(int chunkX, int chunkZ, World w, BiConsumer consumer) { synchronized(cacheMap) { - CarverCache cache = cacheMap.computeIfAbsent(w, world -> new CarverCache(world, main, this)); + CarverCache cache = cacheMap.computeIfAbsent(w.getSeed(), world -> new CarverCache(w, main, this)); int carvingRadius = getCarvingRadius(); for(int x = chunkX - carvingRadius; x <= chunkX + carvingRadius; x++) { for(int z = chunkZ - carvingRadius; z <= chunkZ + carvingRadius; z++) { diff --git a/common/src/main/java/com/dfsek/terra/commands/AddonsCommand.java b/common/src/main/java/com/dfsek/terra/commands/AddonsCommand.java new file mode 100644 index 000000000..d775de66b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/AddonsCommand.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.commands; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; + +@Command( + usage = "/terra addons" +) +public class AddonsCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @Override + public void execute(CommandSender sender) { + sender.sendMessage("Installed Addons:"); + main.getAddons().forEach(addon -> sender.sendMessage(" - " + addon.getName() + " v" + addon.getVersion() + " by " + addon.getAuthor())); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/CommandUtil.java b/common/src/main/java/com/dfsek/terra/commands/CommandUtil.java new file mode 100644 index 000000000..a9e327d08 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/CommandUtil.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.commands; + +import com.dfsek.terra.api.command.CommandManager; +import com.dfsek.terra.api.command.exception.MalformedCommandException; +import com.dfsek.terra.commands.biome.BiomeCommand; +import com.dfsek.terra.commands.geometry.GeometryCommand; +import com.dfsek.terra.commands.profiler.ProfileCommand; +import com.dfsek.terra.commands.structure.StructureCommand; + +public final class CommandUtil { + public static void registerAll(CommandManager manager) throws MalformedCommandException { + manager.register("structure", StructureCommand.class); + manager.register("profile", ProfileCommand.class); + manager.register("reload", ReloadCommand.class); + manager.register("addons", AddonsCommand.class); + manager.register("version", VersionCommand.class); + manager.register("getblock", GetBlockCommand.class); + manager.register("packs", PacksCommand.class); + manager.register("biome", BiomeCommand.class); + manager.register("geometry", GeometryCommand.class); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/GetBlockCommand.java b/common/src/main/java/com/dfsek/terra/commands/GetBlockCommand.java new file mode 100644 index 000000000..a57dd75f2 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/GetBlockCommand.java @@ -0,0 +1,28 @@ +package com.dfsek.terra.commands; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; + +@WorldCommand +@DebugCommand +@PlayerCommand +@Command( + usage = "/terra getblock" +) +public class GetBlockCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @Override + public void execute(CommandSender sender) { + Player player = (Player) sender; + sender.sendMessage("Block: " + main.getWorld(player.getWorld()).getUngeneratedBlock(player.getLocation()).getAsString()); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/PacksCommand.java b/common/src/main/java/com/dfsek/terra/commands/PacksCommand.java new file mode 100644 index 000000000..875ca8ea1 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/PacksCommand.java @@ -0,0 +1,35 @@ +package com.dfsek.terra.commands; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.config.lang.LangUtil; +import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.config.pack.ConfigPackTemplate; + +@Command( + usage = "/terra packs" +) +public class PacksCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @Override + public void execute(CommandSender sender) { + CheckedRegistry registry = main.getConfigRegistry(); + + if(registry.entries().size() == 0) { + LangUtil.send("command.packs.none", sender); + return; + } + + LangUtil.send("command.packs.main", sender); + registry.entries().forEach(entry -> { + ConfigPackTemplate template = entry.getTemplate(); + LangUtil.send("command.packs.pack", sender, template.getID(), template.getAuthor(), template.getVersion()); + }); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/ReloadCommand.java b/common/src/main/java/com/dfsek/terra/commands/ReloadCommand.java new file mode 100644 index 000000000..e78909c04 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/ReloadCommand.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.commands; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.config.lang.LangUtil; + +@Command( + usage = "/terra reload" +) +public class ReloadCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @Override + public void execute(CommandSender sender) { + if(!main.reload()) { + LangUtil.send("command.reload-error", sender); + } else { + LangUtil.send("command.reload", sender); + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/VersionCommand.java b/common/src/main/java/com/dfsek/terra/commands/VersionCommand.java new file mode 100644 index 000000000..7e8521b1c --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/VersionCommand.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.commands; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.config.lang.LangUtil; + +@Command( + usage = "/terra version" +) +public class VersionCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @Override + public void execute(CommandSender sender) { + String terraVersion = main.getVersion(); + LangUtil.send("command.version", sender, terraVersion, main.platformName()); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/biome/BiomeCommand.java b/common/src/main/java/com/dfsek/terra/commands/biome/BiomeCommand.java new file mode 100644 index 000000000..8871f736c --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/biome/BiomeCommand.java @@ -0,0 +1,45 @@ +package com.dfsek.terra.commands.biome; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.Subcommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; +import com.dfsek.terra.config.lang.LangUtil; + +@Command( + subcommands = { + @Subcommand( + value = "info", + aliases = {"i"}, + clazz = BiomeInfoCommand.class + ), + @Subcommand( + value = "locate", + aliases = {"l"}, + clazz = BiomeLocateCommand.class + ) + }, + usage = "/terra biome" +) +@WorldCommand +@PlayerCommand +public class BiomeCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @Override + public void execute(CommandSender sender) { + Player player = (Player) sender; + + BiomeProvider provider = main.getWorld(player.getWorld()).getBiomeProvider(); + UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome(player.getLocation()); + LangUtil.send("command.biome.in", sender, biome.getID()); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/biome/BiomeInfoCommand.java b/common/src/main/java/com/dfsek/terra/commands/biome/BiomeInfoCommand.java new file mode 100644 index 000000000..4fe3fe2ac --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/biome/BiomeInfoCommand.java @@ -0,0 +1,52 @@ +package com.dfsek.terra.commands.biome; + +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Argument; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; +import com.dfsek.terra.commands.biome.arg.BiomeArgumentParser; +import com.dfsek.terra.commands.biome.tab.BiomeTabCompleter; +import com.dfsek.terra.config.templates.BiomeTemplate; +import com.dfsek.terra.world.population.items.TerraStructure; + +import java.util.List; + +@Command( + arguments = { + @Argument( + value = "biome", + tabCompleter = BiomeTabCompleter.class, + argumentParser = BiomeArgumentParser.class + ) + } +) +public class BiomeInfoCommand implements CommandTemplate { + @ArgumentTarget("biome") + private TerraBiome biome; + + @Override + public void execute(CommandSender sender) { + + sender.sendMessage("Biome info for \"" + biome.getID() + "\"."); + sender.sendMessage("Vanilla biome: " + biome.getVanillaBiomes()); + + if(biome instanceof UserDefinedBiome) { + BiomeTemplate bio = ((UserDefinedBiome) biome).getConfig(); + + if(bio.getExtend() != null) sender.sendMessage("Extends: " + bio.getExtend()); + + List structureConfigs = bio.getStructures(); + + if(structureConfigs.size() == 0) sender.sendMessage("No Structures"); + else { + sender.sendMessage("-------Structures-------"); + for(TerraStructure c : structureConfigs) { + sender.sendMessage(" - " + c.getTemplate().getID()); + } + } + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/biome/BiomeLocateCommand.java b/common/src/main/java/com/dfsek/terra/commands/biome/BiomeLocateCommand.java new file mode 100644 index 000000000..b6ef00483 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/biome/BiomeLocateCommand.java @@ -0,0 +1,78 @@ +package com.dfsek.terra.commands.biome; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Argument; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.Switch; +import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; +import com.dfsek.terra.api.command.annotation.inject.SwitchTarget; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.command.arg.IntegerArgumentParser; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.locate.AsyncBiomeFinder; +import com.dfsek.terra.commands.biome.arg.BiomeArgumentParser; +import com.dfsek.terra.commands.biome.tab.BiomeTabCompleter; +import com.dfsek.terra.config.lang.LangUtil; + +import java.util.Locale; + +@PlayerCommand +@WorldCommand +@Command( + arguments = { + @Argument( + value = "biome", + tabCompleter = BiomeTabCompleter.class, + argumentParser = BiomeArgumentParser.class + ), + @Argument( + value = "radius", + required = false, + defaultValue = "1000", + argumentParser = IntegerArgumentParser.class + ) + }, + switches = { + @Switch( + value = "teleport", + aliases = {"t", "tp"} + ) + } +) +public class BiomeLocateCommand implements CommandTemplate { + + @ArgumentTarget("radius") + private Integer radius; + + @ArgumentTarget("biome") + private TerraBiome biome; + + @SwitchTarget("teleport") + private boolean teleport; + + @Inject + private TerraPlugin main; + + @Override + public void execute(CommandSender sender) { + + Player player = (Player) sender; + + new Thread(new AsyncBiomeFinder(main.getWorld(player.getWorld()).getBiomeProvider(), biome, player.getLocation().clone().multiply((1D / main.getTerraConfig().getBiomeSearchResolution())), 0, radius, location -> { + if(location != null) { + sender.sendMessage(String.format("The nearest %s is at [%d, ~, %d] (%.1f blocks away)", biome.getID().toLowerCase(Locale.ROOT), location.getBlockX(), location.getBlockZ(), location.add(new Vector3(0, player.getLocation().getY(), 0)).distance(player.getLocation().toVector()))); + if(teleport) { + main.runPossiblyUnsafeTask(() -> player.setLocation(new Location(player.getWorld(), location.getX(), player.getLocation().getY(), location.getZ()))); + } + } else LangUtil.send("command.biome.unable-to-locate", sender); + }, main), "Biome Location Thread").start(); + + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/biome/arg/BiomeArgumentParser.java b/common/src/main/java/com/dfsek/terra/commands/biome/arg/BiomeArgumentParser.java new file mode 100644 index 000000000..251036d39 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/biome/arg/BiomeArgumentParser.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.commands.biome.arg; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.arg.ArgumentParser; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.world.biome.TerraBiome; + +public class BiomeArgumentParser implements ArgumentParser { + @Inject + private TerraPlugin main; + + @Override + public TerraBiome parse(CommandSender sender, String arg) { + Player player = (Player) sender; + return main.getWorld(player.getWorld()).getConfig().getBiomeRegistry().get(arg); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/biome/tab/BiomeTabCompleter.java b/common/src/main/java/com/dfsek/terra/commands/biome/tab/BiomeTabCompleter.java new file mode 100644 index 000000000..f2461c532 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/biome/tab/BiomeTabCompleter.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.commands.biome.tab; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.tab.TabCompleter; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.world.biome.TerraBiome; + +import java.util.List; +import java.util.stream.Collectors; + +public class BiomeTabCompleter implements TabCompleter { + @Inject + private TerraPlugin main; + + @Override + public List complete(CommandSender sender) { + Player player = (Player) sender; + return main.getWorld(player.getWorld()).getConfig().getBiomeRegistry().entries().stream().map(TerraBiome::getID).collect(Collectors.toList()); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/geometry/DeformedSphereCommand.java b/common/src/main/java/com/dfsek/terra/commands/geometry/DeformedSphereCommand.java new file mode 100644 index 000000000..46ce84559 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/geometry/DeformedSphereCommand.java @@ -0,0 +1,65 @@ +package com.dfsek.terra.commands.geometry; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Argument; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.arg.DoubleArgumentParser; +import com.dfsek.terra.api.command.arg.IntegerArgumentParser; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.math.noise.samplers.noise.simplex.OpenSimplex2Sampler; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.math.voxel.DeformedSphere; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; + +import java.util.concurrent.ThreadLocalRandom; + +@DebugCommand +@PlayerCommand +@Command( + arguments = { + @Argument( + value = "radius", + argumentParser = IntegerArgumentParser.class + ), + @Argument( + value = "deform", + argumentParser = DoubleArgumentParser.class + ), + @Argument( + value = "frequency", + argumentParser = DoubleArgumentParser.class + ) + }, + usage = "/terra geometry deformedsphere " +) +public class DeformedSphereCommand implements CommandTemplate { + @ArgumentTarget("radius") + private Integer radius; + + @ArgumentTarget("deform") + private Double deform; + + @ArgumentTarget("frequency") + private Double frequency; + + @Inject + private TerraPlugin main; + + @Override + public void execute(CommandSender sender) { + Player player = (Player) sender; + + OpenSimplex2Sampler noise = new OpenSimplex2Sampler(ThreadLocalRandom.current().nextInt()); + noise.setFrequency(frequency); + + DeformedSphere sphere = new DeformedSphere(player.getLocation().toVector(), radius, deform, noise); + for(Vector3 v : sphere.getGeometry()) { + v.toLocation(player.getWorld()).getBlock().setBlockData(main.getWorldHandle().createBlockData("minecraft:stone"), false); + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/geometry/GeometryCommand.java b/common/src/main/java/com/dfsek/terra/commands/geometry/GeometryCommand.java new file mode 100644 index 000000000..d41bc8506 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/geometry/GeometryCommand.java @@ -0,0 +1,39 @@ +package com.dfsek.terra.commands.geometry; + +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.Subcommand; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.config.lang.LangUtil; + + +@DebugCommand +@PlayerCommand +@Command( + subcommands = { + @Subcommand( + value = "sphere", + clazz = SphereCommand.class, + aliases = {"s"} + ), + @Subcommand( + value = "deformedsphere", + clazz = DeformedSphereCommand.class, + aliases = {"df"} + ), + @Subcommand( + value = "tube", + clazz = TubeCommand.class, + aliases = {"t"} + ) + }, + usage = "/terra geometry" +) +public class GeometryCommand implements CommandTemplate { + @Override + public void execute(CommandSender sender) { + LangUtil.send("command.geometry.main-menu", sender); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/geometry/SphereCommand.java b/common/src/main/java/com/dfsek/terra/commands/geometry/SphereCommand.java new file mode 100644 index 000000000..7d8586e6a --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/geometry/SphereCommand.java @@ -0,0 +1,44 @@ +package com.dfsek.terra.commands.geometry; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Argument; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.arg.IntegerArgumentParser; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.math.voxel.Sphere; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; + +@DebugCommand +@PlayerCommand +@Command( + arguments = { + @Argument( + value = "radius", + argumentParser = IntegerArgumentParser.class + ) + }, + usage = "/terra geometry sphere " +) +public class SphereCommand implements CommandTemplate { + @ArgumentTarget("radius") + private Integer radius; + + @Inject + private TerraPlugin main; + + @Override + public void execute(CommandSender sender) { + Player player = (Player) sender; + + Sphere sphere = new Sphere(player.getLocation().toVector(), radius); + for(Vector3 v : sphere.getGeometry()) { + v.toLocation(player.getWorld()).getBlock().setBlockData(main.getWorldHandle().createBlockData("minecraft:stone"), false); + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/geometry/TubeCommand.java b/common/src/main/java/com/dfsek/terra/commands/geometry/TubeCommand.java new file mode 100644 index 000000000..b24694762 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/geometry/TubeCommand.java @@ -0,0 +1,49 @@ +package com.dfsek.terra.commands.geometry; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Argument; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.arg.IntegerArgumentParser; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.math.voxel.Tube; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.util.generic.pair.Pair; + +@DebugCommand +@PlayerCommand +@Command( + arguments = { + @Argument( + value = "radius", + argumentParser = IntegerArgumentParser.class + ) + }, + usage = "/terra geometry tube " +) +public class TubeCommand implements CommandTemplate { + @ArgumentTarget("radius") + private Integer radius; + + @Inject + private TerraPlugin main; + + @Override + public void execute(CommandSender sender) { + Player player = (Player) sender; + + Pair locations = main.getWorldHandle().getSelectedLocation(player); + + Tube tube = new Tube(locations.getLeft().toVector(), locations.getRight().toVector(), radius); + + for(Vector3 v : tube.getGeometry()) { + v.toLocation(player.getWorld()).getBlock().setBlockData(main.getWorldHandle().createBlockData("minecraft:stone"), false); + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileCommand.java b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileCommand.java new file mode 100644 index 000000000..c81164363 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileCommand.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.commands.profiler; + +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.Subcommand; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.config.lang.LangUtil; + +@Command( + subcommands = { + @Subcommand(value = "query", aliases = {"q"}, clazz = ProfileQueryCommand.class), + @Subcommand(value = "start", aliases = {"s"}, clazz = ProfileStartCommand.class), + @Subcommand(value = "stop", aliases = {"st"}, clazz = ProfileStopCommand.class), + @Subcommand(value = "reset", aliases = {"r"}, clazz = ProfileResetCommand.class) + }, + usage = "Commands to enable/disable/query/reset the profiler." +) +@WorldCommand +@PlayerCommand +@DebugCommand +public class ProfileCommand implements CommandTemplate { + @Override + public void execute(CommandSender sender) { + LangUtil.send("command.profile.main-menu", sender); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileQueryCommand.java b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileQueryCommand.java new file mode 100644 index 000000000..16f383b2d --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileQueryCommand.java @@ -0,0 +1,28 @@ +package com.dfsek.terra.commands.profiler; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.world.TerraWorld; + +@Command +@WorldCommand +@PlayerCommand +@DebugCommand +public class ProfileQueryCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @Override + public void execute(CommandSender sender) { + Player player = (Player) sender; + TerraWorld world = main.getWorld(player.getWorld()); + player.sendMessage(world.getProfiler().getResultsFormatted()); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileResetCommand.java b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileResetCommand.java new file mode 100644 index 000000000..1a4c47e6e --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileResetCommand.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.commands.profiler; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.world.TerraWorld; + +@Command +@WorldCommand +@PlayerCommand +@DebugCommand +public class ProfileResetCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @Override + public void execute(CommandSender sender) { + Player player = (Player) sender; + TerraWorld world = main.getWorld(player.getWorld()); + world.getProfiler().reset(); + player.sendMessage("Profiler reset."); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStartCommand.java b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStartCommand.java new file mode 100644 index 000000000..36dcec85b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStartCommand.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.commands.profiler; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.world.TerraWorld; + +@Command +@WorldCommand +@PlayerCommand +@DebugCommand +public class ProfileStartCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @Override + public void execute(CommandSender sender) { + Player player = (Player) sender; + TerraWorld world = main.getWorld(player.getWorld()); + world.getProfiler().setProfiling(true); + player.sendMessage("Profiling enabled."); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStopCommand.java b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStopCommand.java new file mode 100644 index 000000000..64e46fe39 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStopCommand.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.commands.profiler; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.world.TerraWorld; + +@Command +@WorldCommand +@PlayerCommand +@DebugCommand +public class ProfileStopCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @Override + public void execute(CommandSender sender) { + Player player = (Player) sender; + TerraWorld world = main.getWorld(player.getWorld()); + world.getProfiler().setProfiling(false); + player.sendMessage("Profiling disabled."); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/SpawnCommand.java b/common/src/main/java/com/dfsek/terra/commands/structure/SpawnCommand.java new file mode 100644 index 000000000..490de66b4 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/structure/SpawnCommand.java @@ -0,0 +1,48 @@ +package com.dfsek.terra.commands.structure; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.structures.parser.lang.constants.NumericConstant; +import com.dfsek.terra.api.structures.script.TerraImplementationArguments; +import com.dfsek.terra.api.structures.script.functions.CheckFunction; +import com.dfsek.terra.api.structures.structure.Rotation; +import com.dfsek.terra.api.structures.structure.buffer.StructureBuffer; +import com.dfsek.terra.api.structures.tokenizer.Position; +import com.dfsek.terra.api.util.FastRandom; + +import java.util.HashMap; + +@DebugCommand +@PlayerCommand +@WorldCommand +@Command( + usage = "/terra spawn" +) +public class SpawnCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @Override + public void execute(CommandSender sender) { + Player player = (Player) sender; + Location p = player.getLocation(); + int x = p.getBlockX(); + int y = p.getBlockY(); + int z = p.getBlockZ(); + Position dummy = new Position(0, 0); + + String check = new CheckFunction(main, new NumericConstant(0, dummy), new NumericConstant(0, dummy), new NumericConstant(0, dummy), dummy).apply(new TerraImplementationArguments(new StructureBuffer( + new com.dfsek.terra.api.math.vector.Location(player.getWorld(), x, y, z) + ), Rotation.NONE, new FastRandom(), 0), new HashMap<>()); + + sender.sendMessage("Found: " + check); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/StructureCommand.java b/common/src/main/java/com/dfsek/terra/commands/structure/StructureCommand.java new file mode 100644 index 000000000..ad095ac70 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/structure/StructureCommand.java @@ -0,0 +1,39 @@ +package com.dfsek.terra.commands.structure; + +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.Subcommand; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.config.lang.LangUtil; + +@Command( + subcommands = { + @Subcommand( + clazz = StructureExportCommand.class, + value = "export", + aliases = "ex" + ), + @Subcommand( + clazz = StructureLoadCommand.class, + value = "load", + aliases = "ld" + ), + @Subcommand( + clazz = SpawnCommand.class, + value = "spawn", + aliases = "s" + ), + @Subcommand( + clazz = StructureLocateCommand.class, + value = "locate", + aliases = "l" + ) + }, + usage = "/te structure" +) +public class StructureCommand implements CommandTemplate { + @Override + public void execute(CommandSender sender) { + LangUtil.send("command.structure.main-menu", sender); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/ExportCommand.java b/common/src/main/java/com/dfsek/terra/commands/structure/StructureExportCommand.java similarity index 54% rename from platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/ExportCommand.java rename to common/src/main/java/com/dfsek/terra/commands/structure/StructureExportCommand.java index 77ec5abef..47dd42a25 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/ExportCommand.java +++ b/common/src/main/java/com/dfsek/terra/commands/structure/StructureExportCommand.java @@ -1,40 +1,56 @@ -package com.dfsek.terra.bukkit.command.command.structure; +package com.dfsek.terra.commands.structure; -import com.dfsek.terra.bukkit.command.PlayerCommand; -import com.dfsek.terra.bukkit.structure.WorldEditUtil; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockState; -import org.bukkit.block.Sign; -import org.bukkit.block.data.BlockData; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Argument; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.state.BlockState; +import com.dfsek.terra.api.platform.block.state.Sign; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.util.generic.pair.Pair; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; -import java.util.Collections; -import java.util.List; -public class ExportCommand extends PlayerCommand { - public ExportCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } +@PlayerCommand +@WorldCommand +@DebugCommand +@Command( + arguments = { + @Argument( + value = "id" + ) + }, + usage = "/terra structure export " +) +public class StructureExportCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @ArgumentTarget("id") + private String id; @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - Location[] l = WorldEditUtil.getSelectionLocations(sender); - if(l == null) return true; + public void execute(CommandSender sender) { + Player player = (Player) sender; - Location l1 = l[0]; - Location l2 = l[1]; + Pair l = main.getWorldHandle().getSelectedLocation(player); - StringBuilder scriptBuilder = new StringBuilder("id \"" + args[0] + "\";\nnum y = 0;\n"); + Location l1 = l.getLeft(); + Location l2 = l.getRight(); + + StringBuilder scriptBuilder = new StringBuilder("id \"" + id + "\";\nnum y = 0;\n"); int centerX = 0; int centerY = 0; @@ -63,24 +79,24 @@ public class ExportCommand extends PlayerCommand { Block block = new Location(l1.getWorld(), x, y, z).getBlock(); BlockData data = block.getBlockData(); - if(block.getType().equals(Material.STRUCTURE_VOID)) continue; + if(block.getBlockData().isStructureVoid()) continue; BlockState state = block.getState(); if(state instanceof Sign) { Sign sign = (Sign) state; if(sign.getLine(0).equals("[TERRA]")) { - data = Bukkit.createBlockData(sign.getLine(2) + sign.getLine(3)); + data = main.getWorldHandle().createBlockData(sign.getLine(2) + sign.getLine(3)); } } - if(!data.getMaterial().equals(Material.STRUCTURE_VOID)) { + if(!data.isStructureVoid()) { scriptBuilder.append("block(").append(x - l1.getBlockX() - centerX).append(", y + ").append(y - l1.getBlockY() - centerY).append(", ").append(z - l1.getBlockZ() - centerZ).append(", ") .append("\""); - scriptBuilder.append(data.getAsString(false)).append("\");\n"); + scriptBuilder.append(data.getAsString()).append("\");\n"); } } } } - File file = new File(getMain().getDataFolder() + File.separator + "export" + File.separator + "structures", args[0] + ".tesf"); + File file = new File(main.getDataFolder() + File.separator + "export" + File.separator + "structures", id + ".tesf"); try { file.getParentFile().mkdirs(); file.createNewFile(); @@ -93,29 +109,6 @@ public class ExportCommand extends PlayerCommand { e.printStackTrace(); } - - sender.sendMessage("Exported structure to " + file.getAbsolutePath()); - return true; - } - - @Override - public String getName() { - return "export"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 1; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); } } diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/StructureLoadCommand.java b/common/src/main/java/com/dfsek/terra/commands/structure/StructureLoadCommand.java new file mode 100644 index 000000000..ae1327b11 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/structure/StructureLoadCommand.java @@ -0,0 +1,92 @@ +package com.dfsek.terra.commands.structure; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Argument; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.Switch; +import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; +import com.dfsek.terra.api.command.annotation.inject.SwitchTarget; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.command.arg.IntegerArgumentParser; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.structures.script.StructureScript; +import com.dfsek.terra.api.structures.structure.Rotation; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.commands.structure.argument.ScriptArgumentParser; +import com.dfsek.terra.commands.structure.completer.RotationCompleter; +import com.dfsek.terra.commands.structure.completer.ScriptCompleter; + +import java.util.concurrent.ThreadLocalRandom; + +@PlayerCommand +@DebugCommand +@WorldCommand +@Command( + arguments = { + @Argument( + value = "structure", + tabCompleter = ScriptCompleter.class, + argumentParser = ScriptArgumentParser.class + ), + @Argument( + value = "rotation", + required = false, + tabCompleter = RotationCompleter.class, + argumentParser = IntegerArgumentParser.class, + defaultValue = "0" + ) + }, + switches = { + @Switch(value = "chunk", + aliases = "c" + ) + }, + usage = "/terra structure load [ROTATION] [-c]" +) +public class StructureLoadCommand implements CommandTemplate { + @ArgumentTarget("rotation") + private Integer rotation = 0; + + @SwitchTarget("chunk") + private boolean chunk; + + @ArgumentTarget("structure") + private StructureScript script; + + @Inject + private TerraPlugin main; + + @Override + public void execute(CommandSender sender) { + System.out.println(rotation); + + Player player = (Player) sender; + + long t = System.nanoTime(); + FastRandom random = new FastRandom(ThreadLocalRandom.current().nextLong()); + Rotation r; + try { + r = Rotation.fromDegrees(rotation); + } catch(Exception e) { + sender.sendMessage("Invalid rotation: " + rotation); + return; + } + if(script == null) { + sender.sendMessage("Invalid structure."); + return; + } + if(this.chunk) { + script.execute(player.getLocation(), player.getWorld().getChunkAt(player.getLocation()), random, r); + } else { + script.execute(player.getLocation(), random, r); + } + long l = System.nanoTime() - t; + + sender.sendMessage("Took " + ((double) l) / 1000000 + "ms"); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/StructureLocateCommand.java b/common/src/main/java/com/dfsek/terra/commands/structure/StructureLocateCommand.java new file mode 100644 index 000000000..0e04c3ec4 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/structure/StructureLocateCommand.java @@ -0,0 +1,75 @@ +package com.dfsek.terra.commands.structure; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Argument; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.Switch; +import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; +import com.dfsek.terra.api.command.annotation.inject.SwitchTarget; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.command.arg.IntegerArgumentParser; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.world.locate.AsyncStructureFinder; +import com.dfsek.terra.commands.structure.argument.StructureArgumentParser; +import com.dfsek.terra.commands.structure.completer.StructureCompleter; +import com.dfsek.terra.config.lang.LangUtil; +import com.dfsek.terra.world.population.items.TerraStructure; + +import java.util.Locale; + +@PlayerCommand +@WorldCommand +@Command( + arguments = { + @Argument( + value = "structure", + tabCompleter = StructureCompleter.class, + argumentParser = StructureArgumentParser.class + ), + @Argument( + value = "radius", + required = false, + defaultValue = "100", + argumentParser = IntegerArgumentParser.class + ) + }, + switches = { + @Switch( + value = "teleport", + aliases = {"t", "tp"} + ) + } +) +public class StructureLocateCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @ArgumentTarget("structure") + private TerraStructure structure; + + @ArgumentTarget("radius") + private Integer radius; + + @SwitchTarget("teleport") + private boolean teleport; + + @Override + public void execute(CommandSender sender) { + Player player = (Player) sender; + + new Thread(new AsyncStructureFinder(main.getWorld(player.getWorld()).getBiomeProvider(), structure, player.getLocation().clone().multiply((1D / main.getTerraConfig().getBiomeSearchResolution())), 0, radius, location -> { + if(location != null) { + sender.sendMessage(String.format("The nearest %s is at [%d, ~, %d] (%.1f blocks away)", structure.getTemplate().getID().toLowerCase(Locale.ROOT), location.getBlockX(), location.getBlockZ(), location.add(new Vector3(0, player.getLocation().getY(), 0)).distance(player.getLocation().toVector()))); + if(teleport) { + main.runPossiblyUnsafeTask(() -> player.setLocation(new Location(player.getWorld(), location.getX(), player.getLocation().getY(), location.getZ()))); + } + } else LangUtil.send("command.biome.unable-to-locate", sender); + }, main), "Biome Location Thread").start(); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/argument/ScriptArgumentParser.java b/common/src/main/java/com/dfsek/terra/commands/structure/argument/ScriptArgumentParser.java new file mode 100644 index 000000000..3797c08cd --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/structure/argument/ScriptArgumentParser.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.commands.structure.argument; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.arg.ArgumentParser; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.structures.script.StructureScript; + +public class ScriptArgumentParser implements ArgumentParser { + @Inject + private TerraPlugin main; + + @Override + public StructureScript parse(CommandSender sender, String arg) { + return main.getWorld(((Player) sender).getWorld()).getConfig().getScriptRegistry().get(arg); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/argument/StructureArgumentParser.java b/common/src/main/java/com/dfsek/terra/commands/structure/argument/StructureArgumentParser.java new file mode 100644 index 000000000..dce50ac65 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/structure/argument/StructureArgumentParser.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.commands.structure.argument; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.arg.ArgumentParser; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.world.population.items.TerraStructure; + +public class StructureArgumentParser implements ArgumentParser { + @Inject + private TerraPlugin main; + + @Override + public TerraStructure parse(CommandSender sender, String arg) { + return main.getWorld(((Player) sender).getWorld()).getConfig().getStructureRegistry().get(arg); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/completer/RotationCompleter.java b/common/src/main/java/com/dfsek/terra/commands/structure/completer/RotationCompleter.java new file mode 100644 index 000000000..3bfed746d --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/structure/completer/RotationCompleter.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.commands.structure.completer; + +import com.dfsek.terra.api.command.tab.TabCompleter; +import com.dfsek.terra.api.platform.CommandSender; + +import java.util.Arrays; +import java.util.List; + +public class RotationCompleter implements TabCompleter { + @Override + public List complete(CommandSender sender) { + return Arrays.asList("0", "90", "180", "270"); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/completer/ScriptCompleter.java b/common/src/main/java/com/dfsek/terra/commands/structure/completer/ScriptCompleter.java new file mode 100644 index 000000000..24f927baa --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/structure/completer/ScriptCompleter.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.commands.structure.completer; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.tab.TabCompleter; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.structures.script.StructureScript; + +import java.util.List; +import java.util.stream.Collectors; + +public class ScriptCompleter implements TabCompleter { + @Inject + private TerraPlugin main; + + @Override + public List complete(CommandSender sender) { + return main.getWorld(((Player) sender).getWorld()).getConfig().getScriptRegistry().entries().stream().map(StructureScript::getId).collect(Collectors.toList()); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/completer/StructureCompleter.java b/common/src/main/java/com/dfsek/terra/commands/structure/completer/StructureCompleter.java new file mode 100644 index 000000000..a2b5b1dad --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/structure/completer/StructureCompleter.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.commands.structure.completer; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.tab.TabCompleter; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; + +import java.util.ArrayList; +import java.util.List; + +public class StructureCompleter implements TabCompleter { + @Inject + private TerraPlugin main; + + @Override + public List complete(CommandSender sender) { + Player player = (Player) sender; + return new ArrayList<>(main.getWorld(player.getWorld()).getConfig().getStructureRegistry().keys()); + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/GenericLoaders.java b/common/src/main/java/com/dfsek/terra/config/GenericLoaders.java index 52cdf965c..0726b8d97 100644 --- a/common/src/main/java/com/dfsek/terra/config/GenericLoaders.java +++ b/common/src/main/java/com/dfsek/terra/config/GenericLoaders.java @@ -2,20 +2,24 @@ package com.dfsek.terra.config; import com.dfsek.tectonic.loading.TypeRegistry; import com.dfsek.terra.api.LoaderRegistrar; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.addons.TerraAddon; import com.dfsek.terra.api.math.GridSpawn; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.math.noise.samplers.ImageSampler; import com.dfsek.terra.api.math.noise.samplers.noise.CellularSampler; +import com.dfsek.terra.api.platform.block.BlockType; +import com.dfsek.terra.api.util.collections.MaterialSet; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.util.seeded.SourceSeeded; import com.dfsek.terra.api.util.seeded.StageSeeded; +import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource; +import com.dfsek.terra.api.world.biome.pipeline.stages.ExpanderStage; +import com.dfsek.terra.api.world.biome.pipeline.stages.MutatorStage; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.biome.provider.ImageBiomeProvider; import com.dfsek.terra.api.world.palette.holder.PaletteHolder; import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder; -import com.dfsek.terra.biome.pipeline.stages.ExpanderStage; -import com.dfsek.terra.biome.pipeline.stages.MutatorStage; -import com.dfsek.terra.biome.provider.BiomeProvider; -import com.dfsek.terra.biome.provider.ImageBiomeProvider; import com.dfsek.terra.carving.CarverPalette; import com.dfsek.terra.config.loaders.LinkedHashMapLoader; import com.dfsek.terra.config.loaders.MaterialSetLoader; @@ -29,6 +33,7 @@ import com.dfsek.terra.config.loaders.config.TreeLayerLoader; import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader; import com.dfsek.terra.config.loaders.config.biome.SourceBuilderLoader; import com.dfsek.terra.config.loaders.config.biome.StageBuilderLoader; +import com.dfsek.terra.config.loaders.config.biome.templates.source.NoiseSourceTemplate; import com.dfsek.terra.config.loaders.config.biome.templates.stage.expander.ExpanderStageTemplate; import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderListMutatorTemplate; import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderMutatorTemplate; @@ -44,7 +49,6 @@ import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.Normal import com.dfsek.terra.config.loaders.palette.CarverPaletteLoader; import com.dfsek.terra.config.loaders.palette.PaletteHolderLoader; import com.dfsek.terra.config.loaders.palette.PaletteLayerLoader; -import com.dfsek.terra.util.MaterialSet; import com.dfsek.terra.world.population.items.flora.FloraLayer; import com.dfsek.terra.world.population.items.flora.TerraFlora; import com.dfsek.terra.world.population.items.ores.Ore; @@ -85,6 +89,7 @@ public class GenericLoaders implements LoaderRegistrar { .registerLoader(ReplaceListMutatorTemplate.class, ReplaceListMutatorTemplate::new) .registerLoader(BorderMutatorTemplate.class, BorderMutatorTemplate::new) .registerLoader(BorderListMutatorTemplate.class, BorderListMutatorTemplate::new) + .registerLoader(NoiseSourceTemplate.class, NoiseSourceTemplate::new) .registerLoader(FunctionTemplate.class, FunctionTemplate::new) .registerLoader(LinkedHashMap.class, new LinkedHashMapLoader()) .registerLoader(CarverPalette.class, new CarverPaletteLoader()) @@ -93,11 +98,17 @@ public class GenericLoaders implements LoaderRegistrar { .registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader()) .registerLoader(ImageSampler.Channel.class, (t, object, cf) -> ImageSampler.Channel.valueOf((String) object)) .registerLoader(BiomeProvider.Type.class, (t, object, cf) -> BiomeProvider.Type.valueOf((String) object)) + .registerLoader(BiomeSource.Type.class, (t, object, cf) -> BiomeSource.Type.valueOf((String) object)) .registerLoader(ImageBiomeProvider.Align.class, (t, object, cf) -> ImageBiomeProvider.Align.valueOf((String) object)) .registerLoader(ExpanderStage.Type.class, (t, object, cf) -> ExpanderStage.Type.valueOf((String) object)) .registerLoader(MutatorStage.Type.class, (t, object, cf) -> MutatorStage.Type.valueOf((String) object)) .registerLoader(CellularSampler.ReturnType.class, (t, object, cf) -> CellularSampler.ReturnType.valueOf((String) object)) .registerLoader(CellularSampler.DistanceFunction.class, (t, object, cf) -> CellularSampler.DistanceFunction.valueOf((String) object)) .registerLoader(TerraFlora.Search.class, (t, o, l) -> TerraFlora.Search.valueOf(o.toString())); + + if(main != null) { + registry.registerLoader(TerraAddon.class, main.getAddons()) + .registerLoader(BlockType.class, (t, object, cf) -> main.getWorldHandle().createBlockData((String) object).getBlockType()); + } } } diff --git a/common/src/main/java/com/dfsek/terra/config/PluginConfig.java b/common/src/main/java/com/dfsek/terra/config/PluginConfig.java index 1d058e96a..e1112dcf4 100644 --- a/common/src/main/java/com/dfsek/terra/config/PluginConfig.java +++ b/common/src/main/java/com/dfsek/terra/config/PluginConfig.java @@ -5,8 +5,9 @@ import com.dfsek.tectonic.annotations.Value; import com.dfsek.tectonic.config.ConfigTemplate; import com.dfsek.tectonic.exception.ConfigException; import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.util.JarUtil; +import com.dfsek.terra.api.util.logging.Logger; import java.io.File; import java.io.FileInputStream; @@ -14,7 +15,6 @@ import java.io.IOException; import java.net.URISyntaxException; import java.time.Duration; import java.util.jar.JarFile; -import java.util.logging.Logger; @SuppressWarnings("FieldMayBeFinal") public class PluginConfig implements ConfigTemplate { @@ -63,7 +63,7 @@ public class PluginConfig implements ConfigTemplate { private int maxRecursion = 1000; public void load(TerraPlugin main) { - Logger logger = main.getLogger(); + Logger logger = main.logger(); logger.info("Loading config values"); try(FileInputStream file = new FileInputStream(new File(main.getDataFolder(), "config.yml"))) { ConfigLoader loader = new ConfigLoader(); diff --git a/common/src/main/java/com/dfsek/terra/config/builder/BiomeBuilder.java b/common/src/main/java/com/dfsek/terra/config/builder/BiomeBuilder.java new file mode 100644 index 000000000..a454cb07c --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/builder/BiomeBuilder.java @@ -0,0 +1,10 @@ +package com.dfsek.terra.config.builder; + +import com.dfsek.terra.api.platform.world.Biome; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; +import com.dfsek.terra.api.util.seeded.SeededBuilder; +import com.dfsek.terra.api.world.biome.TerraBiome; + +public interface BiomeBuilder extends SeededBuilder { + ProbabilityCollection getVanillaBiomes(); +} diff --git a/common/src/main/java/com/dfsek/terra/config/builder/UserDefinedBiomeBuilder.java b/common/src/main/java/com/dfsek/terra/config/builder/UserDefinedBiomeBuilder.java new file mode 100644 index 000000000..904a541c9 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/builder/UserDefinedBiomeBuilder.java @@ -0,0 +1,69 @@ +package com.dfsek.terra.config.builder; + +import com.dfsek.paralithic.eval.parser.Scope; +import com.dfsek.paralithic.eval.tokenizer.ParseException; +import com.dfsek.terra.api.math.noise.NoiseSampler; +import com.dfsek.terra.api.math.noise.samplers.ExpressionSampler; +import com.dfsek.terra.api.math.noise.samplers.noise.ConstantSampler; +import com.dfsek.terra.api.platform.world.Biome; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; +import com.dfsek.terra.api.util.seeded.NoiseSeeded; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; +import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; +import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.config.templates.BiomeTemplate; +import com.dfsek.terra.world.generation.WorldGenerator; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class UserDefinedBiomeBuilder implements BiomeBuilder { + private final BiomeTemplate template; + private final ConfigPack pack; + + private final Map biomeMap = new ConcurrentHashMap<>(); + + public UserDefinedBiomeBuilder(BiomeTemplate template, ConfigPack pack) { + this.template = template; + this.pack = pack; + } + + @Override + public UserDefinedBiome apply(Long seed) { + synchronized(biomeMap) { + return biomeMap.computeIfAbsent(seed, + s -> { + NoiseSampler noise; + NoiseSampler elevation; + NoiseSampler carving; + Scope varScope = new Scope().withParent(pack.getVarScope()); + + template.getVariables().forEach(varScope::create); + + Map noiseBuilderMap = pack.getTemplate().getNoiseBuilderMap(); + Map functionTemplateMap = new LinkedHashMap<>(pack.getTemplate().getFunctions()); + + functionTemplateMap.putAll(template.getFunctions()); + + try { + noise = new ExpressionSampler(template.getNoiseEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap); + elevation = template.getElevationEquation() == null ? new ConstantSampler(0) : new ExpressionSampler(template.getElevationEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap); + carving = new ExpressionSampler(template.getCarvingEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap); + } catch(ParseException e) { + throw new RuntimeException(e); + } + + WorldGenerator generator = new WorldGenerator(template.getPalette(), template.getSlantPalette(), noise, elevation, carving, template.getBiomeNoise().apply(seed), template.getElevationWeight(), + template.getBlendDistance(), template.getBlendStep(), template.getBlendWeight()); + return new UserDefinedBiome(template.getVanilla(), generator, template); + } + ); + } + } + + @Override + public ProbabilityCollection getVanillaBiomes() { + return template.getVanilla(); + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/dummy/DummyWorld.java b/common/src/main/java/com/dfsek/terra/config/dummy/DummyWorld.java new file mode 100644 index 000000000..06cd712fc --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/dummy/DummyWorld.java @@ -0,0 +1,75 @@ +package com.dfsek.terra.config.dummy; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.entity.Entity; +import com.dfsek.terra.api.platform.entity.EntityType; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; + +import java.io.File; +import java.util.UUID; + +public class DummyWorld implements World { + @Override + public Object getHandle() { + throw new UnsupportedOperationException("Cannot get handle of DummyWorld"); + } + + @Override + public long getSeed() { + return 2403L; + } + + @Override + public int getMaxHeight() { + return 255; + } + + @Override + public ChunkGenerator getGenerator() { + return () -> (GeneratorWrapper) () -> null; + } + + @Override + public String getName() { + return "DUMMY"; + } + + @Override + public UUID getUID() { + return UUID.randomUUID(); + } + + @Override + public boolean isChunkGenerated(int x, int z) { + return false; + } + + @Override + public Chunk getChunkAt(int x, int z) { + throw new UnsupportedOperationException("Cannot get chunk in DummyWorld"); + } + + @Override + public File getWorldFolder() { + throw new UnsupportedOperationException("Cannot get folder of DummyWorld"); + } + + @Override + public Block getBlockAt(int x, int y, int z) { + throw new UnsupportedOperationException("Cannot get block in DummyWorld"); + } + + @Override + public Entity spawnEntity(Location location, EntityType entityType) { + throw new UnsupportedOperationException("Cannot spawn entity in DummyWorld"); + } + + @Override + public int getMinHeight() { + return 0; + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/exception/FileMissingException.java b/common/src/main/java/com/dfsek/terra/config/exception/FileMissingException.java deleted file mode 100644 index c4ac0ecf3..000000000 --- a/common/src/main/java/com/dfsek/terra/config/exception/FileMissingException.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dfsek.terra.config.exception; - -import com.dfsek.tectonic.exception.ConfigException; - -public class FileMissingException extends ConfigException { - private static final long serialVersionUID = 4489395640246760802L; - - public FileMissingException(String message) { - super(message); - } - - public FileMissingException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java index b4f09aa8c..c19ea0988 100644 --- a/common/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java @@ -1,18 +1,12 @@ package com.dfsek.terra.config.factories; -import com.dfsek.paralithic.eval.parser.Scope; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.config.builder.GeneratorBuilder; -import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.config.builder.BiomeBuilder; +import com.dfsek.terra.config.builder.UserDefinedBiomeBuilder; import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.templates.BiomeTemplate; -import java.util.LinkedHashMap; -import java.util.Map; - -public class BiomeFactory implements TerraFactory { +public class BiomeFactory implements ConfigFactory { private final ConfigPack pack; public BiomeFactory(ConfigPack pack) { @@ -20,32 +14,7 @@ public class BiomeFactory implements TerraFactory { } @Override - public UserDefinedBiome build(BiomeTemplate template, TerraPlugin main) { - GeneratorBuilder generatorBuilder = new GeneratorBuilder(); - generatorBuilder.setElevationEquation(template.getElevationEquation()); - generatorBuilder.setNoiseEquation(template.getNoiseEquation()); - generatorBuilder.setCarvingEquation(template.getCarvingEquation()); - generatorBuilder.setNoiseBuilderMap(pack.getTemplate().getNoiseBuilderMap()); - - Map functions = new LinkedHashMap<>(pack.getTemplate().getFunctions()); // linked map to preserve order. - functions.putAll(template.getFunctions()); - generatorBuilder.setFunctionTemplateMap(functions); - - generatorBuilder.setPalettes(template.getPalette()); - generatorBuilder.setSlantPalettes(template.getSlantPalette()); - - Scope vars = new Scope().withParent(pack.getVarScope()); - template.getVariables().forEach(vars::create); - generatorBuilder.setVarScope(vars); - - generatorBuilder.setInterpolateElevation(template.interpolateElevation()); - generatorBuilder.setElevationWeight(template.getElevationWeight()); - generatorBuilder.setBiomeNoise(template.getBiomeNoise()); - generatorBuilder.setBlendDistance(template.getBlendDistance()); - generatorBuilder.setBlendStep(template.getBlendStep()); - generatorBuilder.setBlendWeight(template.getBlendWeight()); - - - return new UserDefinedBiome(template.getVanilla(), generatorBuilder, template); + public BiomeBuilder build(BiomeTemplate template, TerraPlugin main) { + return new UserDefinedBiomeBuilder(template, pack); } } diff --git a/common/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java index 19c16e47e..e572f3e6c 100644 --- a/common/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java @@ -2,7 +2,7 @@ package com.dfsek.terra.config.factories; import com.dfsek.paralithic.eval.tokenizer.ParseException; import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.MathUtil; import com.dfsek.terra.carving.UserDefinedCarver; import com.dfsek.terra.config.pack.ConfigPack; @@ -11,7 +11,7 @@ import com.dfsek.terra.config.templates.CarverTemplate; import java.util.Arrays; import java.util.List; -public class CarverFactory implements TerraFactory { +public class CarverFactory implements ConfigFactory { private final ConfigPack pack; public CarverFactory(ConfigPack pack) { diff --git a/common/src/main/java/com/dfsek/terra/config/factories/TerraFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/ConfigFactory.java similarity index 66% rename from common/src/main/java/com/dfsek/terra/config/factories/TerraFactory.java rename to common/src/main/java/com/dfsek/terra/config/factories/ConfigFactory.java index 8e7d5ee82..cf676a8d6 100644 --- a/common/src/main/java/com/dfsek/terra/config/factories/TerraFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/ConfigFactory.java @@ -2,8 +2,8 @@ package com.dfsek.terra.config.factories; import com.dfsek.tectonic.config.ConfigTemplate; import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; -public interface TerraFactory { +public interface ConfigFactory { O build(C config, TerraPlugin main) throws LoadException; } diff --git a/common/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java index ba51ca3dd..279dbf3e4 100644 --- a/common/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java @@ -1,6 +1,6 @@ package com.dfsek.terra.config.factories; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.world.flora.Flora; @@ -10,7 +10,7 @@ import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder; import com.dfsek.terra.config.templates.FloraTemplate; import com.dfsek.terra.world.population.items.flora.TerraFlora; -public class FloraFactory implements TerraFactory { +public class FloraFactory implements ConfigFactory { @Override public TerraFlora build(FloraTemplate config, TerraPlugin main) { Palette palette = new NoisePalette<>(new WhiteNoiseSampler(2403), false); diff --git a/common/src/main/java/com/dfsek/terra/config/factories/OreFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/OreFactory.java index da74a1a81..fdbf6ea90 100644 --- a/common/src/main/java/com/dfsek/terra/config/factories/OreFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/OreFactory.java @@ -1,13 +1,13 @@ package com.dfsek.terra.config.factories; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.config.templates.OreTemplate; import com.dfsek.terra.world.population.items.ores.DeformedSphereOre; import com.dfsek.terra.world.population.items.ores.Ore; import com.dfsek.terra.world.population.items.ores.VanillaOre; -public class OreFactory implements TerraFactory { +public class OreFactory implements ConfigFactory { @Override public Ore build(OreTemplate config, TerraPlugin main) { BlockData m = config.getMaterial(); diff --git a/common/src/main/java/com/dfsek/terra/config/factories/PaletteFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/PaletteFactory.java index 0e113f216..d4983c076 100644 --- a/common/src/main/java/com/dfsek/terra/config/factories/PaletteFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/PaletteFactory.java @@ -1,13 +1,13 @@ package com.dfsek.terra.config.factories; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.world.palette.NoisePalette; import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder; import com.dfsek.terra.config.templates.PaletteTemplate; -public class PaletteFactory implements TerraFactory> { +public class PaletteFactory implements ConfigFactory> { @Override public Palette build(PaletteTemplate config, TerraPlugin main) { NoisePalette palette = new NoisePalette<>(config.getNoise().apply(2403L), config.getNoise().getDimensions() == 2); diff --git a/common/src/main/java/com/dfsek/terra/config/factories/StructureFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/StructureFactory.java index 5724e2bfa..0fa25315d 100644 --- a/common/src/main/java/com/dfsek/terra/config/factories/StructureFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/StructureFactory.java @@ -1,10 +1,10 @@ package com.dfsek.terra.config.factories; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.config.templates.StructureTemplate; import com.dfsek.terra.world.population.items.TerraStructure; -public class StructureFactory implements TerraFactory { +public class StructureFactory implements ConfigFactory { @Override public TerraStructure build(StructureTemplate config, TerraPlugin main) { return new TerraStructure(config.getStructures(), config.getY(), config.getSpawn(), config); diff --git a/common/src/main/java/com/dfsek/terra/config/factories/TreeFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/TreeFactory.java index 717ad33cd..9d6963e0e 100644 --- a/common/src/main/java/com/dfsek/terra/config/factories/TreeFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/TreeFactory.java @@ -1,11 +1,11 @@ package com.dfsek.terra.config.factories; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.world.tree.Tree; import com.dfsek.terra.config.templates.TreeTemplate; import com.dfsek.terra.world.population.items.tree.TerraTree; -public class TreeFactory implements TerraFactory { +public class TreeFactory implements ConfigFactory { @Override public Tree build(TreeTemplate config, TerraPlugin main) { return new TerraTree(config.getSpawnable(), config.getyOffset(), config.getStructures()); diff --git a/common/src/main/java/com/dfsek/terra/config/lang/LangUtil.java b/common/src/main/java/com/dfsek/terra/config/lang/LangUtil.java index a3d47ccd1..347a1e577 100644 --- a/common/src/main/java/com/dfsek/terra/config/lang/LangUtil.java +++ b/common/src/main/java/com/dfsek/terra/config/lang/LangUtil.java @@ -1,23 +1,21 @@ package com.dfsek.terra.config.lang; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.util.logging.Logger; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.util.jar.JarFile; -import java.util.logging.Level; -import java.util.logging.Logger; import static com.dfsek.terra.api.util.JarUtil.copyResourcesToDirectory; public final class LangUtil { private static Language language; - private static Logger logger; public static void load(String langID, TerraPlugin main) { - logger = main.getLogger(); + Logger logger = main.logger(); File file = new File(main.getDataFolder(), "lang"); try(JarFile jar = new JarFile(new File(TerraPlugin.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) { copyResourcesToDirectory(jar, "lang", file.toString()); @@ -41,10 +39,6 @@ public final class LangUtil { return language; } - public static void log(String messageID, Level level, String... args) { - language.getMessage(messageID).log(logger, level, args); - } - public static void send(String messageID, CommandSender sender, String... args) { language.getMessage(messageID).send(sender, args); } diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java index c06333917..a98ca9837 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java @@ -3,8 +3,8 @@ package com.dfsek.terra.config.loaders; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.platform.block.MaterialData; -import com.dfsek.terra.util.MaterialSet; +import com.dfsek.terra.api.platform.block.BlockType; +import com.dfsek.terra.api.util.collections.MaterialSet; import java.lang.reflect.Type; import java.util.List; @@ -18,7 +18,7 @@ public class MaterialSetLoader implements TypeLoader { for(String string : stringData) { try { - set.add(configLoader.loadClass(MaterialData.class, string)); + set.add(configLoader.loadClass(BlockType.class, string)); } catch(NullPointerException e) { throw new LoadException("Invalid data identifier \"" + string + "\"", e); } diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java index 28a471ce1..050281b4d 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java @@ -3,7 +3,7 @@ package com.dfsek.terra.config.loaders; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/Types.java b/common/src/main/java/com/dfsek/terra/config/loaders/Types.java index bb58ce950..255c652c0 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/Types.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/Types.java @@ -1,24 +1,20 @@ package com.dfsek.terra.config.loaders; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; +import com.dfsek.terra.api.world.biome.TerraBiome; import com.dfsek.terra.api.world.flora.Flora; import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.tree.Tree; -import com.dfsek.terra.biome.TerraBiome; import java.lang.reflect.Type; import java.util.Map; -import java.util.Set; /** * Class to hold Type instances for types with generics. */ @SuppressWarnings("unused") public final class Types { - public static final Type MATERIAL_SET_TYPE; - public static final Type MATERIAL_PROBABILITY_COLLECTION_TYPE; public static final Type BLOCK_DATA_PALETTE_TYPE; public static final Type BLOCK_DATA_PROBABILITY_COLLECTION_TYPE; public static final Type FLORA_PROBABILITY_COLLECTION_TYPE; @@ -27,8 +23,6 @@ public final class Types { public static final Type TERRA_BIOME_TERRA_BIOME_PROBABILITY_COLLECTION_MAP; static { - MATERIAL_SET_TYPE = getType("materialSet"); - MATERIAL_PROBABILITY_COLLECTION_TYPE = getType("materialProbabilityCollection"); BLOCK_DATA_PALETTE_TYPE = getType("blockDataPalette"); BLOCK_DATA_PROBABILITY_COLLECTION_TYPE = getType("blockDataProbabilityCollection"); FLORA_PROBABILITY_COLLECTION_TYPE = getType("floraProbabilityCollection"); @@ -37,9 +31,7 @@ public final class Types { TERRA_BIOME_TERRA_BIOME_PROBABILITY_COLLECTION_MAP = getType("terraBiomeProbabilityCollectionMap"); } - private Set materialSet; private Palette blockDataPalette; - private ProbabilityCollection materialProbabilityCollection; private ProbabilityCollection blockDataProbabilityCollection; private ProbabilityCollection floraProbabilityCollection; private ProbabilityCollection treeProbabilityCollection; diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java index 411dd0b5e..719bf9b91 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java @@ -4,9 +4,9 @@ import com.dfsek.tectonic.exception.ConfigException; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.world.flora.Flora; import com.dfsek.terra.config.loaders.Types; diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java index fa2b98181..0fddd9705 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java @@ -3,9 +3,9 @@ package com.dfsek.terra.config.loaders.config; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.world.tree.Tree; import com.dfsek.terra.config.loaders.Types; diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/BiomeProviderBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/BiomeProviderBuilderLoader.java index d7f4d045f..718d33907 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/BiomeProviderBuilderLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/BiomeProviderBuilderLoader.java @@ -3,10 +3,10 @@ package com.dfsek.terra.config.loaders.config.biome; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.biome.provider.BiomeProvider; -import com.dfsek.terra.config.loaders.config.biome.templates.source.BiomePipelineTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.source.ImageProviderTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.source.SingleBiomeProviderTemplate; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; +import com.dfsek.terra.config.loaders.config.biome.templates.provider.BiomePipelineTemplate; +import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProviderTemplate; +import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiomeProviderTemplate; import java.lang.reflect.Type; import java.util.Map; diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/SourceBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/SourceBuilderLoader.java index 03a8d5527..33f1dcd42 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/SourceBuilderLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/SourceBuilderLoader.java @@ -3,12 +3,14 @@ package com.dfsek.terra.config.loaders.config.biome; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.util.seeded.SourceSeeded; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.pipeline.source.RandomSource; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource; +import com.dfsek.terra.api.world.biome.pipeline.source.RandomSource; import com.dfsek.terra.config.loaders.Types; +import com.dfsek.terra.config.loaders.config.biome.templates.source.NoiseSourceTemplate; import java.lang.reflect.Type; import java.util.Map; @@ -19,12 +21,10 @@ public class SourceBuilderLoader implements TypeLoader { public SourceSeeded load(Type t, Object c, ConfigLoader loader) throws LoadException { Map source = (Map) c; - String type = source.get("type").toString(); + BiomeSource.Type type = loader.loadClass(BiomeSource.Type.class, source.get("type")); - if("NOISE".equals(type)) { - ProbabilityCollection sourceBiomes = (ProbabilityCollection) loader.loadType(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, source.get("biomes")); - NoiseSeeded sourceNoise = loader.loadClass(NoiseSeeded.class, source.get("noise")); - return seed -> new RandomSource(sourceBiomes, sourceNoise.apply(seed)); + if(type == BiomeSource.Type.NOISE) { + return loader.loadClass(NoiseSourceTemplate.class, source); } throw new LoadException("No such loader type: " + type); } diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/StageBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/StageBuilderLoader.java index f173c1364..58c464fde 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/StageBuilderLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/StageBuilderLoader.java @@ -4,8 +4,8 @@ import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; import com.dfsek.terra.api.util.seeded.StageSeeded; -import com.dfsek.terra.biome.pipeline.stages.ExpanderStage; -import com.dfsek.terra.biome.pipeline.stages.MutatorStage; +import com.dfsek.terra.api.world.biome.pipeline.stages.ExpanderStage; +import com.dfsek.terra.api.world.biome.pipeline.stages.MutatorStage; import com.dfsek.terra.config.loaders.config.biome.templates.stage.expander.ExpanderStageTemplate; import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderListMutatorTemplate; import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderMutatorTemplate; diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/BiomePipelineTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/BiomePipelineTemplate.java similarity index 70% rename from common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/BiomePipelineTemplate.java rename to common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/BiomePipelineTemplate.java index 46d810866..31f448553 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/BiomePipelineTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/BiomePipelineTemplate.java @@ -1,14 +1,13 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.source; +package com.dfsek.terra.config.loaders.config.biome.templates.provider; import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.util.seeded.SourceSeeded; import com.dfsek.terra.api.util.seeded.StageSeeded; -import com.dfsek.terra.biome.pipeline.BiomePipeline; -import com.dfsek.terra.biome.provider.BiomeProvider; -import com.dfsek.terra.biome.provider.StandardBiomeProvider; -import com.dfsek.terra.registry.config.BiomeRegistry; +import com.dfsek.terra.api.world.biome.pipeline.BiomePipeline; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.biome.provider.StandardBiomeProvider; import java.util.List; @@ -25,8 +24,7 @@ public class BiomePipelineTemplate extends BiomeProviderTemplate { @Value("pipeline.source") private SourceSeeded source; - public BiomePipelineTemplate(BiomeRegistry registry, TerraPlugin main) { - super(registry); + public BiomePipelineTemplate(TerraPlugin main) { this.main = main; } diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/BiomeProviderTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/BiomeProviderTemplate.java similarity index 76% rename from common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/BiomeProviderTemplate.java rename to common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/BiomeProviderTemplate.java index b0a65d85e..2b0799b87 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/BiomeProviderTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/BiomeProviderTemplate.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.source; +package com.dfsek.terra.config.loaders.config.biome.templates.provider; import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; @@ -6,11 +6,9 @@ import com.dfsek.tectonic.loading.object.ObjectTemplate; import com.dfsek.terra.api.math.noise.NoiseSampler; import com.dfsek.terra.api.math.noise.samplers.noise.ConstantSampler; import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.biome.provider.BiomeProvider; -import com.dfsek.terra.registry.config.BiomeRegistry; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; public abstract class BiomeProviderTemplate implements ObjectTemplate, BiomeProvider.BiomeProviderBuilder { - protected final BiomeRegistry registry; @Value("resolution") @Default protected int resolution = 1; @@ -33,10 +31,6 @@ public abstract class BiomeProviderTemplate implements ObjectTemplate biomes; + @Value("image.name") + private BufferedImage image; + + @Value("image.align") + private ImageBiomeProvider.Align align; + + public ImageProviderTemplate(Registry set) { + this.biomes = set; + } + + @Override + public BiomeProvider build(long seed) { + return new ImageBiomeProvider(biomes.entries().stream().map(biomeBuilder -> biomeBuilder.apply(seed)).collect(Collectors.toSet()), image, resolution, align); + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/SingleBiomeProviderTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/SingleBiomeProviderTemplate.java new file mode 100644 index 000000000..525315454 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/SingleBiomeProviderTemplate.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.config.loaders.config.biome.templates.provider; + +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.biome.provider.SingleBiomeProvider; +import com.dfsek.terra.config.builder.BiomeBuilder; + +public class SingleBiomeProviderTemplate extends BiomeProviderTemplate { + @Value("biome") + private BiomeBuilder biome; + + public SingleBiomeProviderTemplate() { + } + + @Override + public BiomeProvider build(long seed) { + return new SingleBiomeProvider(biome.apply(seed)); + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/ImageProviderTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/ImageProviderTemplate.java deleted file mode 100644 index e92379d7e..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/ImageProviderTemplate.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.source; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.biome.provider.BiomeProvider; -import com.dfsek.terra.biome.provider.ImageBiomeProvider; -import com.dfsek.terra.registry.config.BiomeRegistry; - -import java.awt.image.BufferedImage; - -public class ImageProviderTemplate extends BiomeProviderTemplate { - @Value("image.name") - private BufferedImage image; - - @Value("image.align") - private ImageBiomeProvider.Align align; - - public ImageProviderTemplate(BiomeRegistry registry) { - super(registry); - } - - @Override - public BiomeProvider build(long seed) { - return new ImageBiomeProvider(registry, image, resolution, align); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/NoiseSourceTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/NoiseSourceTemplate.java new file mode 100644 index 000000000..7df6255d0 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/NoiseSourceTemplate.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.config.loaders.config.biome.templates.source; + +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; +import com.dfsek.terra.api.util.seeded.NoiseSeeded; +import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource; +import com.dfsek.terra.api.world.biome.pipeline.source.RandomSource; +import com.dfsek.terra.config.builder.BiomeBuilder; + +public class NoiseSourceTemplate extends SourceTemplate { + @Value("noise") + private NoiseSeeded noise; + + @Value("biomes") + private ProbabilityCollection biomes; + + @Override + public BiomeSource apply(Long seed) { + return new RandomSource(biomes.map((biome) -> biome.apply(seed), false), noise.apply(seed)); + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/SingleBiomeProviderTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/SingleBiomeProviderTemplate.java deleted file mode 100644 index 811656cd4..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/SingleBiomeProviderTemplate.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.source; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.provider.BiomeProvider; -import com.dfsek.terra.biome.provider.SingleBiomeProvider; -import com.dfsek.terra.registry.config.BiomeRegistry; - -public class SingleBiomeProviderTemplate extends BiomeProviderTemplate { - @Value("biome") - private TerraBiome biome; - - public SingleBiomeProviderTemplate(BiomeRegistry registry) { - super(registry); - } - - @Override - public BiomeProvider build(long seed) { - return new SingleBiomeProvider(biome); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/SourceTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/SourceTemplate.java new file mode 100644 index 000000000..cee30713b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/SourceTemplate.java @@ -0,0 +1,12 @@ +package com.dfsek.terra.config.loaders.config.biome.templates.source; + +import com.dfsek.tectonic.loading.object.ObjectTemplate; +import com.dfsek.terra.api.util.seeded.SourceSeeded; +import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource; + +public abstract class SourceTemplate implements ObjectTemplate, SourceSeeded { + @Override + public SourceSeeded get() { + return this; + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/StageTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/StageTemplate.java index 041185648..151eaedef 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/StageTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/StageTemplate.java @@ -5,7 +5,7 @@ import com.dfsek.tectonic.loading.object.ObjectTemplate; import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.util.seeded.SeededBuilder; import com.dfsek.terra.api.util.seeded.StageSeeded; -import com.dfsek.terra.biome.pipeline.stages.Stage; +import com.dfsek.terra.api.world.biome.pipeline.stages.Stage; public abstract class StageTemplate implements ObjectTemplate>, StageSeeded { @Value("noise") diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/expander/ExpanderStageTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/expander/ExpanderStageTemplate.java index 0d25cdbc0..fb396ddbc 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/expander/ExpanderStageTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/expander/ExpanderStageTemplate.java @@ -1,8 +1,8 @@ package com.dfsek.terra.config.loaders.config.biome.templates.stage.expander; -import com.dfsek.terra.biome.pipeline.expand.FractalExpander; -import com.dfsek.terra.biome.pipeline.stages.ExpanderStage; -import com.dfsek.terra.biome.pipeline.stages.Stage; +import com.dfsek.terra.api.world.biome.pipeline.expand.FractalExpander; +import com.dfsek.terra.api.world.biome.pipeline.stages.ExpanderStage; +import com.dfsek.terra.api.world.biome.pipeline.stages.Stage; import com.dfsek.terra.config.loaders.config.biome.templates.stage.StageTemplate; public class ExpanderStageTemplate extends StageTemplate { diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderListMutatorTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderListMutatorTemplate.java index 3a10d7b47..76146a088 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderListMutatorTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderListMutatorTemplate.java @@ -1,13 +1,16 @@ package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator; import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.ProbabilityCollection; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.pipeline.mutator.BiomeMutator; -import com.dfsek.terra.biome.pipeline.mutator.BorderListMutator; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; +import com.dfsek.terra.api.world.biome.pipeline.mutator.BorderListMutator; +import com.dfsek.terra.config.builder.BiomeBuilder; +import java.util.HashMap; import java.util.Map; +@SuppressWarnings("unused") public class BorderListMutatorTemplate extends MutatorStageTemplate { @Value("from") private String from; @@ -16,14 +19,18 @@ public class BorderListMutatorTemplate extends MutatorStageTemplate { private String defaultReplace; @Value("default-to") - private ProbabilityCollection defaultTo; + private ProbabilityCollection defaultTo; @Value("replace") - private Map> replace; + private Map> replace; @Override public BiomeMutator build(long seed) { - return new BorderListMutator(replace, from, defaultReplace, noise.apply(seed), defaultTo); + Map> replaceMap = new HashMap<>(); + + replace.forEach((keyBuilder, replacements) -> replaceMap.put(keyBuilder.apply(seed), replacements.map(replacement -> replacement.apply(seed), true))); + + return new BorderListMutator(replaceMap, from, defaultReplace, noise.apply(seed), defaultTo.map(biomeBuilder -> biomeBuilder.apply(seed), true)); } } diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderMutatorTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderMutatorTemplate.java index 094c68dd6..5502a412f 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderMutatorTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderMutatorTemplate.java @@ -1,10 +1,10 @@ package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator; import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.ProbabilityCollection; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.pipeline.mutator.BiomeMutator; -import com.dfsek.terra.biome.pipeline.mutator.BorderMutator; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; +import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; +import com.dfsek.terra.api.world.biome.pipeline.mutator.BorderMutator; +import com.dfsek.terra.config.builder.BiomeBuilder; @SuppressWarnings("unused") public class BorderMutatorTemplate extends MutatorStageTemplate { @@ -15,10 +15,10 @@ public class BorderMutatorTemplate extends MutatorStageTemplate { private String replace; @Value("to") - private ProbabilityCollection to; + private ProbabilityCollection to; @Override public BiomeMutator build(long seed) { - return new BorderMutator(from, replace, noise.apply(seed), to); + return new BorderMutator(from, replace, noise.apply(seed), to.map(biomeBuilder -> biomeBuilder.apply(seed), true)); } } diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/MutatorStageTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/MutatorStageTemplate.java index 47ea30afd..84283ffcc 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/MutatorStageTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/MutatorStageTemplate.java @@ -1,8 +1,8 @@ package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator; -import com.dfsek.terra.biome.pipeline.mutator.BiomeMutator; -import com.dfsek.terra.biome.pipeline.stages.MutatorStage; -import com.dfsek.terra.biome.pipeline.stages.Stage; +import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; +import com.dfsek.terra.api.world.biome.pipeline.stages.MutatorStage; +import com.dfsek.terra.api.world.biome.pipeline.stages.Stage; import com.dfsek.terra.config.loaders.config.biome.templates.stage.StageTemplate; public abstract class MutatorStageTemplate extends StageTemplate { diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/ReplaceListMutatorTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/ReplaceListMutatorTemplate.java index 9ac41f078..d40eec7b4 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/ReplaceListMutatorTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/ReplaceListMutatorTemplate.java @@ -1,11 +1,13 @@ package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator; import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.ProbabilityCollection; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.pipeline.mutator.BiomeMutator; -import com.dfsek.terra.biome.pipeline.mutator.ReplaceListMutator; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; +import com.dfsek.terra.api.world.biome.pipeline.mutator.ReplaceListMutator; +import com.dfsek.terra.config.builder.BiomeBuilder; +import java.util.HashMap; import java.util.Map; @SuppressWarnings("unused") @@ -14,13 +16,17 @@ public class ReplaceListMutatorTemplate extends MutatorStageTemplate { private String defaultFrom; @Value("default-to") - private ProbabilityCollection defaultTo; + private ProbabilityCollection defaultTo; @Value("to") - private Map> replace; + private Map> replace; @Override public BiomeMutator build(long seed) { - return new ReplaceListMutator(replace, defaultFrom, defaultTo, noise.apply(seed)); + Map> replaceMap = new HashMap<>(); + + replace.forEach((biomeBuilder, biomeBuilders) -> replaceMap.put(biomeBuilder.apply(seed), biomeBuilders.map(builder -> builder.apply(seed), true))); + + return new ReplaceListMutator(replaceMap, defaultFrom, defaultTo.map(biomeBuilder -> biomeBuilder.apply(seed), true), noise.apply(seed)); } } diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/ReplaceMutatorTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/ReplaceMutatorTemplate.java index 9239d4ddd..fbe801fbf 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/ReplaceMutatorTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/ReplaceMutatorTemplate.java @@ -1,10 +1,10 @@ package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator; import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.ProbabilityCollection; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.pipeline.mutator.BiomeMutator; -import com.dfsek.terra.biome.pipeline.mutator.ReplaceMutator; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; +import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; +import com.dfsek.terra.api.world.biome.pipeline.mutator.ReplaceMutator; +import com.dfsek.terra.config.builder.BiomeBuilder; @SuppressWarnings("unused") public class ReplaceMutatorTemplate extends MutatorStageTemplate { @@ -12,10 +12,10 @@ public class ReplaceMutatorTemplate extends MutatorStageTemplate { private String from; @Value("to") - private ProbabilityCollection to; + private ProbabilityCollection to; @Override public BiomeMutator build(long seed) { - return new ReplaceMutator(from, to, noise.apply(seed)); + return new ReplaceMutator(from, to.map(biomeBuilder -> biomeBuilder.apply(seed), true), noise.apply(seed)); } } diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/SmoothMutatorTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/SmoothMutatorTemplate.java index c01d2dbd1..a5c27c54a 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/SmoothMutatorTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/SmoothMutatorTemplate.java @@ -1,7 +1,7 @@ package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator; -import com.dfsek.terra.biome.pipeline.mutator.BiomeMutator; -import com.dfsek.terra.biome.pipeline.mutator.SmoothMutator; +import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; +import com.dfsek.terra.api.world.biome.pipeline.mutator.SmoothMutator; public class SmoothMutatorTemplate extends MutatorStageTemplate { @Override diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/CellularNoiseTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/CellularNoiseTemplate.java index 3852742b9..90a53d277 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/CellularNoiseTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/CellularNoiseTemplate.java @@ -39,7 +39,7 @@ public class CellularNoiseTemplate extends NoiseTemplate { @Override public NoiseSampler apply(Long seed) { - CellularSampler sampler = new CellularSampler((int) (long) seed); + CellularSampler sampler = new CellularSampler((int) (long) seed + salt); sampler.setNoiseLookup(lookup.apply(seed)); sampler.setFrequency(frequency); sampler.setJitterModifier(cellularJitter); diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/ExpressionFunctionTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/ExpressionFunctionTemplate.java index 256106a99..79aa5a41a 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/ExpressionFunctionTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/ExpressionFunctionTemplate.java @@ -1,5 +1,7 @@ package com.dfsek.terra.config.loaders.config.sampler.templates.noise; +import com.dfsek.paralithic.eval.parser.Parser; +import com.dfsek.paralithic.eval.parser.Scope; import com.dfsek.paralithic.eval.tokenizer.ParseException; import com.dfsek.paralithic.functions.Function; import com.dfsek.tectonic.annotations.Default; @@ -9,12 +11,15 @@ import com.dfsek.tectonic.exception.ValidationException; import com.dfsek.terra.api.math.noise.NoiseSampler; import com.dfsek.terra.api.math.noise.samplers.noise.ExpressionFunction; import com.dfsek.terra.api.math.paralithic.BlankFunction; +import com.dfsek.terra.api.math.paralithic.defined.UserDefinedFunction; import com.dfsek.terra.api.math.paralithic.noise.NoiseFunction2; import com.dfsek.terra.api.math.paralithic.noise.NoiseFunction3; import com.dfsek.terra.api.util.seeded.NoiseSeeded; +import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.SamplerTemplate; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; @@ -29,19 +34,16 @@ public class ExpressionFunctionTemplate extends SamplerTemplate functions = new HashMap<>(); + private LinkedHashMap functions = new LinkedHashMap<>(); + + @Value("expressions") + @Default + private LinkedHashMap expressions = new LinkedHashMap<>(); @Override public NoiseSampler apply(Long seed) { try { - Map noiseFunctionMap = new HashMap<>(); - - functions.forEach((id, function) -> { - if(function.getDimensions() == 2) { - noiseFunctionMap.put(id, new NoiseFunction2(function.apply(seed))); - } else noiseFunctionMap.put(id, new NoiseFunction3(function.apply(seed))); - }); - + Map noiseFunctionMap = generateFunctions(seed); return new ExpressionFunction(noiseFunctionMap, equation, vars); } catch(ParseException e) { throw new IllegalStateException(e); @@ -51,17 +53,28 @@ public class ExpressionFunctionTemplate extends SamplerTemplate noiseFunctionMap = new HashMap<>(); - - functions.forEach((id, function) -> { - if(function.getDimensions() == 2) { - noiseFunctionMap.put(id, new BlankFunction(2)); - } else noiseFunctionMap.put(id, new BlankFunction(3)); - }); + Map noiseFunctionMap = generateFunctions(0L); new ExpressionFunction(noiseFunctionMap, equation, vars); } catch(ParseException e) { throw new ValidationException("Errors occurred while parsing noise equation: ", e); } return super.validate(); } + + private Map generateFunctions(Long seed) throws ParseException { + Map noiseFunctionMap = new HashMap<>(); + + for(Map.Entry entry : expressions.entrySet()) { + System.out.println(entry); + noiseFunctionMap.put(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue(), new Parser(), new Scope())); + } + + functions.forEach((id, function) -> { + if(function.getDimensions() == 2) { + noiseFunctionMap.put(id, new NoiseFunction2(function.apply(seed))); + } else noiseFunctionMap.put(id, new NoiseFunction3(function.apply(seed))); + }); + + return noiseFunctionMap; + } } diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/GaborNoiseTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/GaborNoiseTemplate.java new file mode 100644 index 000000000..b15aa75cd --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/GaborNoiseTemplate.java @@ -0,0 +1,40 @@ +package com.dfsek.terra.config.loaders.config.sampler.templates.noise; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.terra.api.math.noise.NoiseSampler; +import com.dfsek.terra.api.math.noise.samplers.noise.GaborNoiseSampler; + +public class GaborNoiseTemplate extends NoiseTemplate { + @Value("rotation") + @Default + private double rotation = 0.25; + + @Value("isotropic") + @Default + private boolean isotropic = true; + + @Value("deviation") + @Default + private double deviation = 1.0; + + @Value("impulses") + @Default + private double impulses = 64d; + + @Value("frequency_0") + @Default + private double f0 = 0.625; + + @Override + public NoiseSampler apply(Long seed) { + GaborNoiseSampler gaborNoiseSampler = new GaborNoiseSampler((int) (long) seed + salt); + gaborNoiseSampler.setFrequency(frequency); + gaborNoiseSampler.setRotation(rotation); + gaborNoiseSampler.setIsotropic(isotropic); + gaborNoiseSampler.setDeviation(deviation); + gaborNoiseSampler.setImpulsesPerKernel(impulses); + gaborNoiseSampler.setFrequency0(f0); + return gaborNoiseSampler; + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/SimpleNoiseTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/SimpleNoiseTemplate.java index 731096c0f..9c1ab1cb2 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/SimpleNoiseTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/SimpleNoiseTemplate.java @@ -14,7 +14,7 @@ public class SimpleNoiseTemplate extends NoiseTemplate { @Override public NoiseSampler apply(Long seed) { - NoiseFunction sampler = samplerSupplier.apply((int) (long) seed); + NoiseFunction sampler = samplerSupplier.apply((int) (long) seed + salt); sampler.setFrequency(frequency); return sampler; } diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/palette/CarverPaletteLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/palette/CarverPaletteLoader.java index ed5bd12fb..696683dd5 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/palette/CarverPaletteLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/palette/CarverPaletteLoader.java @@ -4,11 +4,11 @@ import com.dfsek.tectonic.config.Configuration; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.util.collections.MaterialSet; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.carving.CarverPalette; import com.dfsek.terra.config.loaders.Types; -import com.dfsek.terra.util.MaterialSet; import java.lang.reflect.Type; import java.util.List; diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java index 12c32224c..01a30a2e2 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java @@ -3,9 +3,9 @@ package com.dfsek.terra.config.loaders.palette; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.noise.NoiseSampler; import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder; import com.dfsek.terra.config.loaders.Types; diff --git a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java index d426c6748..5755ec0e9 100644 --- a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java +++ b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java @@ -6,36 +6,39 @@ import com.dfsek.tectonic.exception.ConfigException; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeRegistry; +import com.dfsek.tectonic.loading.object.ObjectTemplate; import com.dfsek.terra.api.LoaderRegistrar; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.api.core.event.events.config.ConfigPackPostLoadEvent; -import com.dfsek.terra.api.core.event.events.config.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.event.events.config.ConfigPackPostLoadEvent; +import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.api.structures.loot.LootTable; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.api.structures.script.StructureScript; import com.dfsek.terra.api.util.seeded.NoiseSeeded; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.api.world.flora.Flora; import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.tree.Tree; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.provider.BiomeProvider; import com.dfsek.terra.carving.UserDefinedCarver; -import com.dfsek.terra.config.exception.FileMissingException; +import com.dfsek.terra.config.builder.BiomeBuilder; +import com.dfsek.terra.config.dummy.DummyWorld; import com.dfsek.terra.config.factories.BiomeFactory; import com.dfsek.terra.config.factories.CarverFactory; +import com.dfsek.terra.config.factories.ConfigFactory; import com.dfsek.terra.config.factories.FloraFactory; import com.dfsek.terra.config.factories.OreFactory; import com.dfsek.terra.config.factories.PaletteFactory; import com.dfsek.terra.config.factories.StructureFactory; -import com.dfsek.terra.config.factories.TerraFactory; import com.dfsek.terra.config.factories.TreeFactory; import com.dfsek.terra.config.fileloaders.FolderLoader; import com.dfsek.terra.config.fileloaders.Loader; import com.dfsek.terra.config.fileloaders.ZIPLoader; -import com.dfsek.terra.config.lang.LangUtil; import com.dfsek.terra.config.loaders.config.BufferedImageLoader; -import com.dfsek.terra.config.loaders.config.biome.templates.source.BiomePipelineTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.source.ImageProviderTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.source.SingleBiomeProviderTemplate; +import com.dfsek.terra.config.loaders.config.biome.templates.provider.BiomePipelineTemplate; +import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProviderTemplate; +import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiomeProviderTemplate; import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader; import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTemplate; import com.dfsek.terra.config.templates.AbstractableTemplate; @@ -46,11 +49,11 @@ import com.dfsek.terra.config.templates.OreTemplate; import com.dfsek.terra.config.templates.PaletteTemplate; import com.dfsek.terra.config.templates.StructureTemplate; import com.dfsek.terra.config.templates.TreeTemplate; -import com.dfsek.terra.registry.FunctionRegistry; -import com.dfsek.terra.registry.TerraRegistry; +import com.dfsek.terra.registry.OpenRegistry; import com.dfsek.terra.registry.config.BiomeRegistry; import com.dfsek.terra.registry.config.CarverRegistry; import com.dfsek.terra.registry.config.FloraRegistry; +import com.dfsek.terra.registry.config.FunctionRegistry; import com.dfsek.terra.registry.config.LootRegistry; import com.dfsek.terra.registry.config.NoiseRegistry; import com.dfsek.terra.registry.config.OreRegistry; @@ -58,7 +61,7 @@ import com.dfsek.terra.registry.config.PaletteRegistry; import com.dfsek.terra.registry.config.ScriptRegistry; import com.dfsek.terra.registry.config.StructureRegistry; import com.dfsek.terra.registry.config.TreeRegistry; -import com.dfsek.terra.world.generation.math.SamplerCache; +import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.population.items.TerraStructure; import com.dfsek.terra.world.population.items.ores.Ore; import org.apache.commons.io.IOUtils; @@ -75,7 +78,7 @@ import java.util.Enumeration; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.logging.Level; +import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -104,8 +107,6 @@ public class ConfigPack implements LoaderRegistrar { private final ConfigLoader selfLoader = new ConfigLoader(); private final Scope varScope = new Scope(); - private final SamplerCache samplerCache; - private final TerraPlugin main; private final Loader loader; @@ -117,7 +118,6 @@ public class ConfigPack implements LoaderRegistrar { this.loader = new FolderLoader(folder.toPath()); this.main = main; long l = System.nanoTime(); - this.samplerCache = new SamplerCache(main); floraRegistry = new FloraRegistry(main); paletteRegistry = new PaletteRegistry(main); treeRegistry = new TreeRegistry(main); @@ -132,7 +132,7 @@ public class ConfigPack implements LoaderRegistrar { try { selfLoader.load(template, new FileInputStream(pack)); - main.getLogger().info("Loading config pack \"" + template.getID() + "\""); + main.logger().info("Loading config pack \"" + template.getID() + "\""); load(l, main); ConfigPackPostTemplate packPostTemplate = new ConfigPackPostTemplate(); @@ -140,12 +140,13 @@ public class ConfigPack implements LoaderRegistrar { biomeProviderBuilder = packPostTemplate.getProviderBuilder(); biomeProviderBuilder.build(0); // Build dummy provider to catch errors at load time. } catch(FileNotFoundException e) { - throw new FileMissingException("No pack.yml file found in " + folder.getAbsolutePath(), e); + throw new LoadException("No pack.yml file found in " + folder.getAbsolutePath(), e); } } catch(Exception e) { - main.getLogger().severe("Failed to load config pack from folder \"" + folder.getAbsolutePath() + "\""); + main.logger().severe("Failed to load config pack from folder \"" + folder.getAbsolutePath() + "\""); throw e; } + toWorldConfig(new TerraWorld(new DummyWorld(), this, main)); // Build now to catch any errors immediately. } public ConfigPack(ZipFile file, TerraPlugin main) throws ConfigException { @@ -153,7 +154,6 @@ public class ConfigPack implements LoaderRegistrar { this.loader = new ZIPLoader(file); this.main = main; long l = System.nanoTime(); - this.samplerCache = new SamplerCache(main); floraRegistry = new FloraRegistry(main); paletteRegistry = new PaletteRegistry(main); treeRegistry = new TreeRegistry(main); @@ -171,10 +171,10 @@ public class ConfigPack implements LoaderRegistrar { if(entry.getName().equals("pack.yml")) pack = entry; } - if(pack == null) throw new FileMissingException("No pack.yml file found in " + file.getName()); + if(pack == null) throw new LoadException("No pack.yml file found in " + file.getName()); selfLoader.load(template, file.getInputStream(pack)); - main.getLogger().info("Loading config pack \"" + template.getID() + "\""); + main.logger().info("Loading config pack \"" + template.getID() + "\""); load(l, main); @@ -187,12 +187,14 @@ public class ConfigPack implements LoaderRegistrar { throw new LoadException("Unable to load pack.yml from ZIP file", e); } } catch(Exception e) { - main.getLogger().severe("Failed to load config pack from ZIP archive \"" + file.getName() + "\""); + main.logger().severe("Failed to load config pack from ZIP archive \"" + file.getName() + "\""); throw e; } + + toWorldConfig(new TerraWorld(new DummyWorld(), this, main)); // Build now to catch any errors immediately. } - public static void buildAll(TerraFactory factory, TerraRegistry registry, List configTemplates, TerraPlugin main) throws LoadException { + public static void buildAll(ConfigFactory factory, OpenRegistry registry, List configTemplates, TerraPlugin main) throws LoadException { for(C template : configTemplates) registry.add(template.getID(), factory.build(template, main)); } @@ -205,10 +207,10 @@ public class ConfigPack implements LoaderRegistrar { loader.open("structures/data", ".tesf").thenEntries(entries -> { for(Map.Entry entry : entries) { - try { - StructureScript structureScript = new StructureScript(entry.getValue(), main, scriptRegistry, lootRegistry, samplerCache, functionRegistry); + try(InputStream stream = entry.getValue()) { + StructureScript structureScript = new StructureScript(stream, main, scriptRegistry, lootRegistry, functionRegistry); scriptRegistry.add(structureScript.getId(), structureScript); - } catch(com.dfsek.terra.api.structures.parser.exceptions.ParseException e) { + } catch(com.dfsek.terra.api.structures.parser.exceptions.ParseException | IOException e) { throw new LoadException("Unable to load script \"" + entry.getKey() + "\"", e); } } @@ -232,15 +234,7 @@ public class ConfigPack implements LoaderRegistrar { .open("biomes", ".yml").then(streams -> buildAll(new BiomeFactory(this), biomeRegistry, abstractConfigLoader.load(streams, () -> new BiomeTemplate(this, main)), main)).close(); main.getEventManager().callEvent(new ConfigPackPostLoadEvent(this)); - LangUtil.log("config-pack.loaded", Level.INFO, template.getID(), String.valueOf((System.nanoTime() - start) / 1000000D), template.getAuthor(), template.getVersion()); - } - - public TerraBiome getBiome(String id) { - return biomeRegistry.get(id); - } - - public List getBiomeIDs() { - return biomeRegistry.entries().stream().map(TerraBiome::getID).collect(Collectors.toList()); + main.logger().info("Loaded config pack \"" + template.getID() + "\" v" + template.getVersion() + " by " + template.getAuthor() + " in " + (System.nanoTime() - start) / 1000000D + "ms."); } public TerraStructure getStructure(String id) { @@ -255,10 +249,6 @@ public class ConfigPack implements LoaderRegistrar { return structureRegistry.entries().stream().map(terraStructure -> terraStructure.getTemplate().getID()).collect(Collectors.toList()); } - public TreeRegistry getTreeRegistry() { - return treeRegistry; - } - public ConfigPackTemplate getTemplate() { return template; } @@ -272,7 +262,7 @@ public class ConfigPack implements LoaderRegistrar { public void register(TypeRegistry registry) { registry .registerLoader(Palette.class, paletteRegistry) - .registerLoader(TerraBiome.class, biomeRegistry) + .registerLoader(BiomeBuilder.class, biomeRegistry) .registerLoader(Flora.class, floraRegistry) .registerLoader(Ore.class, oreRegistry) .registerLoader(Tree.class, treeRegistry) @@ -282,23 +272,12 @@ public class ConfigPack implements LoaderRegistrar { .registerLoader(UserDefinedCarver.class, carverRegistry) .registerLoader(BufferedImage.class, new BufferedImageLoader(loader)) .registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(noiseRegistry)) - .registerLoader(SingleBiomeProviderTemplate.class, () -> new SingleBiomeProviderTemplate(biomeRegistry)) - .registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(biomeRegistry, main)) + .registerLoader(SingleBiomeProviderTemplate.class, SingleBiomeProviderTemplate::new) + .registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(main)) + .registerLoader(ImageProviderTemplate.class, () -> new ImageProviderTemplate(biomeRegistry)) .registerLoader(ImageSamplerTemplate.class, () -> new ImageProviderTemplate(biomeRegistry)); } - public ScriptRegistry getScriptRegistry() { - return scriptRegistry; - } - - public BiomeRegistry getBiomeRegistry() { - return biomeRegistry; - } - - public SamplerCache getSamplerCache() { - return samplerCache; - } - public Set getCarvers() { return carverRegistry.entries(); } @@ -307,35 +286,51 @@ public class ConfigPack implements LoaderRegistrar { return biomeProviderBuilder; } - public FunctionRegistry getFunctionRegistry() { - return functionRegistry; + public CheckedRegistry getScriptRegistry() { + return new CheckedRegistry<>(scriptRegistry); } - public NoiseRegistry getNormalizerRegistry() { - return noiseRegistry; + public CheckedRegistry getBiomeRegistry() { + return new CheckedRegistry<>(biomeRegistry); } - public CarverRegistry getCarverRegistry() { - return carverRegistry; + public CheckedRegistry getTreeRegistry() { + return new CheckedRegistry<>(treeRegistry); } - public FloraRegistry getFloraRegistry() { - return floraRegistry; + public CheckedRegistry> getFunctionRegistry() { + return new CheckedRegistry<>(functionRegistry); } - public LootRegistry getLootRegistry() { - return lootRegistry; + public CheckedRegistry>> getNormalizerRegistry() { + return new CheckedRegistry<>(noiseRegistry); } - public OreRegistry getOreRegistry() { - return oreRegistry; + public CheckedRegistry getCarverRegistry() { + return new CheckedRegistry<>(carverRegistry); } - public PaletteRegistry getPaletteRegistry() { - return paletteRegistry; + public CheckedRegistry getFloraRegistry() { + return new CheckedRegistry<>(floraRegistry); } - public StructureRegistry getStructureRegistry() { - return structureRegistry; + public CheckedRegistry getLootRegistry() { + return new CheckedRegistry<>(lootRegistry); + } + + public CheckedRegistry getOreRegistry() { + return new CheckedRegistry<>(oreRegistry); + } + + public CheckedRegistry> getPaletteRegistry() { + return new CheckedRegistry<>(paletteRegistry); + } + + public CheckedRegistry getStructureRegistry() { + return new CheckedRegistry<>(structureRegistry); + } + + public WorldConfig toWorldConfig(TerraWorld world){ + return new WorldConfig(world, this, main); } } diff --git a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackPostTemplate.java b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackPostTemplate.java index 985740a1a..dd24def46 100644 --- a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackPostTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackPostTemplate.java @@ -2,7 +2,7 @@ package com.dfsek.terra.config.pack; import com.dfsek.tectonic.annotations.Value; import com.dfsek.tectonic.config.ConfigTemplate; -import com.dfsek.terra.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; public class ConfigPackPostTemplate implements ConfigTemplate { @Value("biomes") diff --git a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java index 638a6f4e9..c49d2b667 100644 --- a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java @@ -3,12 +3,15 @@ package com.dfsek.terra.config.pack; import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; import com.dfsek.tectonic.config.ConfigTemplate; +import com.dfsek.terra.api.addons.TerraAddon; import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Set; @SuppressWarnings({"unused", "FieldMayBeFinal"}) public class ConfigPackTemplate implements ConfigTemplate { @@ -18,6 +21,10 @@ public class ConfigPackTemplate implements ConfigTemplate { @Value("noise") private Map noiseBuilderMap; + @Value("addons") + @Default + private Set addons = new HashSet<>(); + @Value("variables") @Default private Map variables = new HashMap<>(); @@ -66,7 +73,7 @@ public class ConfigPackTemplate implements ConfigTemplate { @Default private String version = "0.1.0"; - public Map getFunctions() { + public LinkedHashMap getFunctions() { return functions; } @@ -121,4 +128,8 @@ public class ConfigPackTemplate implements ConfigTemplate { public boolean doBetaCarvers() { return betaCarvers; } + + public Set getAddons() { + return addons; + } } diff --git a/common/src/main/java/com/dfsek/terra/config/pack/WorldConfig.java b/common/src/main/java/com/dfsek/terra/config/pack/WorldConfig.java new file mode 100644 index 000000000..f5f836ee0 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/pack/WorldConfig.java @@ -0,0 +1,124 @@ +package com.dfsek.terra.config.pack; + +import com.dfsek.tectonic.loading.object.ObjectTemplate; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.registry.LockedRegistry; +import com.dfsek.terra.api.structures.loot.LootTable; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.script.StructureScript; +import com.dfsek.terra.api.util.seeded.NoiseSeeded; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.flora.Flora; +import com.dfsek.terra.api.world.palette.Palette; +import com.dfsek.terra.api.world.tree.Tree; +import com.dfsek.terra.carving.UserDefinedCarver; +import com.dfsek.terra.registry.OpenRegistry; +import com.dfsek.terra.world.TerraWorld; +import com.dfsek.terra.world.generation.math.SamplerCache; +import com.dfsek.terra.world.population.items.TerraStructure; +import com.dfsek.terra.world.population.items.ores.Ore; + +import java.util.Set; +import java.util.function.Supplier; + +public class WorldConfig { + private final LockedRegistry scriptRegistry; + private final LockedRegistry biomeRegistry; + private final SamplerCache samplerCache; + private final LockedRegistry carverRegistry; + private final LockedRegistry treeRegistry; + private final LockedRegistry floraRegistry; + private final LockedRegistry lootRegistry; + private final LockedRegistry oreRegistry; + private final LockedRegistry> paletteRegistry; + private final LockedRegistry structureRegistry; + + private final BiomeProvider provider; + + private final TerraWorld world; + private final ConfigPack pack; + + public WorldConfig(TerraWorld world, ConfigPack pack, TerraPlugin main) { + this.world = world; + this.pack = pack; + this.samplerCache = new SamplerCache(main, world); + this.scriptRegistry = new LockedRegistry<>(pack.getScriptRegistry()); + + OpenRegistry biomeOpenRegistry = new OpenRegistry<>(); + pack.getBiomeRegistry().forEach((id, biome) -> biomeOpenRegistry.add(id, biome.apply(world.getWorld().getSeed()))); + + this.biomeRegistry = new LockedRegistry<>(biomeOpenRegistry); + this.carverRegistry = new LockedRegistry<>(pack.getCarverRegistry()); + this.treeRegistry = new LockedRegistry<>(pack.getTreeRegistry()); + this.floraRegistry = new LockedRegistry<>(pack.getFloraRegistry()); + this.lootRegistry = new LockedRegistry<>(pack.getLootRegistry()); + this.oreRegistry = new LockedRegistry<>(pack.getOreRegistry()); + this.paletteRegistry = new LockedRegistry<>(pack.getPaletteRegistry()); + this.structureRegistry = new LockedRegistry<>(pack.getStructureRegistry()); + + this.provider = pack.getBiomeProviderBuilder().build(world.getWorld().getSeed()); + } + + public TerraWorld getWorld() { + return world; + } + + public SamplerCache getSamplerCache() { + return samplerCache; + } + + public Set getCarvers() { + return carverRegistry.entries(); + } + + public LockedRegistry getScriptRegistry() { + return scriptRegistry; + } + + public LockedRegistry getBiomeRegistry() { + return biomeRegistry; + } + + public LockedRegistry getTreeRegistry() { + return treeRegistry; + } + + public LockedRegistry getCarverRegistry() { + return carverRegistry; + } + + public LockedRegistry getFloraRegistry() { + return floraRegistry; + } + + public LockedRegistry getLootRegistry() { + return lootRegistry; + } + + public LockedRegistry getOreRegistry() { + return oreRegistry; + } + + public LockedRegistry> getPaletteRegistry() { + return paletteRegistry; + } + + public LockedRegistry getStructureRegistry() { + return structureRegistry; + } + + public BiomeProvider getProvider() { + return provider; + } + + public Set getStructures() { + return structureRegistry.entries(); + } + + public ConfigPackTemplate getTemplate() { + return pack.getTemplate(); + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java index 230be1ea1..b3a28548b 100644 --- a/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java @@ -8,16 +8,16 @@ import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; import com.dfsek.tectonic.config.ValidatedConfigTemplate; import com.dfsek.tectonic.exception.ValidationException; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.noise.NoiseSampler; import com.dfsek.terra.api.math.noise.samplers.noise.ConstantSampler; import com.dfsek.terra.api.math.paralithic.BlankFunction; import com.dfsek.terra.api.math.paralithic.defined.UserDefinedFunction; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.block.BlockType; import com.dfsek.terra.api.platform.world.Biome; import com.dfsek.terra.api.util.GlueList; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.palette.SinglePalette; @@ -31,6 +31,7 @@ import com.dfsek.terra.world.population.items.ores.OreHolder; import com.dfsek.terra.world.population.items.tree.TreeLayer; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -158,12 +159,12 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf @Value("slabs.palettes") @Abstractable @Default - private Map> slabPalettes; + private Map> slabPalettes; @Value("slabs.stair-palettes") @Abstractable @Default - private Map> stairPalettes; + private Map> stairPalettes; @Value("slant.threshold") @Abstractable @@ -182,7 +183,7 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf @Value("tags") @Default @Abstractable - private Set tags; + private Set tags = new HashSet<>(); @Value("carving") @Abstractable @@ -237,11 +238,11 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf return doSlabs; } - public Map> getSlabPalettes() { + public Map> getSlabPalettes() { return slabPalettes; } - public Map> getStairPalettes() { + public Map> getStairPalettes() { return stairPalettes; } diff --git a/common/src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java index 4f9bf1b12..96cdbde03 100644 --- a/common/src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java @@ -4,9 +4,9 @@ import com.dfsek.tectonic.annotations.Abstractable; import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.block.BlockType; +import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.carving.CarverPalette; -import com.dfsek.terra.util.MaterialSet; import java.util.HashMap; import java.util.Map; @@ -104,7 +104,7 @@ public class CarverTemplate extends AbstractableTemplate { @Value("shift") @Abstractable @Default - private Map shift = new HashMap<>(); + private Map shift = new HashMap<>(); @Value("update") @Abstractable @@ -187,7 +187,7 @@ public class CarverTemplate extends AbstractableTemplate { return inner; } - public Map getShift() { + public Map getShift() { return shift; } diff --git a/common/src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java index 4ca624764..8e1564e4a 100644 --- a/common/src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java @@ -3,8 +3,8 @@ package com.dfsek.terra.config.templates; import com.dfsek.tectonic.annotations.Abstractable; import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; +import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder; -import com.dfsek.terra.util.MaterialSet; import com.dfsek.terra.world.population.items.flora.TerraFlora; import java.util.List; diff --git a/common/src/main/java/com/dfsek/terra/config/templates/OreTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/OreTemplate.java index 9311baedf..7362a4c6a 100644 --- a/common/src/main/java/com/dfsek/terra/config/templates/OreTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/OreTemplate.java @@ -5,7 +5,7 @@ import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.util.MaterialSet; +import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.world.population.items.ores.Ore; @SuppressWarnings({"unused", "FieldMayBeFinal"}) diff --git a/common/src/main/java/com/dfsek/terra/config/templates/StructureTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/StructureTemplate.java index 8da29ddf8..a291ae3f9 100644 --- a/common/src/main/java/com/dfsek/terra/config/templates/StructureTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/StructureTemplate.java @@ -5,10 +5,10 @@ import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; import com.dfsek.tectonic.config.ConfigTemplate; import com.dfsek.terra.api.math.GridSpawn; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.structures.script.StructureScript; import com.dfsek.terra.api.util.GlueList; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import java.util.List; diff --git a/common/src/main/java/com/dfsek/terra/config/templates/TreeTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/TreeTemplate.java index 33702c5a4..008d05d4f 100644 --- a/common/src/main/java/com/dfsek/terra/config/templates/TreeTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/TreeTemplate.java @@ -3,9 +3,9 @@ package com.dfsek.terra.config.templates; import com.dfsek.tectonic.annotations.Abstractable; import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.util.MaterialSet; +import com.dfsek.terra.api.util.collections.MaterialSet; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; @SuppressWarnings({"unused", "FieldMayBeFinal"}) public class TreeTemplate extends AbstractableTemplate { diff --git a/common/src/main/java/com/dfsek/terra/profiler/WorldProfiler.java b/common/src/main/java/com/dfsek/terra/profiler/WorldProfiler.java index 7b3e9c12d..a1ea04908 100644 --- a/common/src/main/java/com/dfsek/terra/profiler/WorldProfiler.java +++ b/common/src/main/java/com/dfsek/terra/profiler/WorldProfiler.java @@ -1,6 +1,7 @@ package com.dfsek.terra.profiler; import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.world.TerraWorld; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import net.jafama.FastMath; @@ -13,7 +14,7 @@ public class WorldProfiler { private boolean isProfiling; public WorldProfiler(World w) { - if(w.getGenerator().getTerraGenerator() == null) + if(!TerraWorld.isTerraWorld(w)) throw new IllegalArgumentException("Attempted to instantiate profiler on non-Terra managed world!"); this.addMeasurement(new Measurement(2500000, DataType.PERIOD_MILLISECONDS), "TotalChunkGenTime") .addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "FloraTime") @@ -21,7 +22,7 @@ public class WorldProfiler { .addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "OreTime") .addMeasurement(new Measurement(5000000, DataType.PERIOD_MILLISECONDS), "CaveTime") .addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "StructureTime"); - ; + isProfiling = false; this.world = w; } diff --git a/common/src/main/java/com/dfsek/terra/registry/FunctionRegistry.java b/common/src/main/java/com/dfsek/terra/registry/FunctionRegistry.java deleted file mode 100644 index dc3689d0a..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/FunctionRegistry.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.dfsek.terra.registry; - -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; - -public class FunctionRegistry extends TerraRegistry> { -} diff --git a/common/src/main/java/com/dfsek/terra/registry/OpenRegistry.java b/common/src/main/java/com/dfsek/terra/registry/OpenRegistry.java new file mode 100644 index 000000000..1cd0b81f2 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/registry/OpenRegistry.java @@ -0,0 +1,92 @@ +package com.dfsek.terra.registry; + +import com.dfsek.tectonic.exception.LoadException; +import com.dfsek.tectonic.loading.ConfigLoader; +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.registry.exception.DuplicateEntryException; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +/** + * Registry implementation with read/write access. For internal use only. + * @param + */ +public class OpenRegistry implements Registry { + private final Map objects = new HashMap<>(); + + @Override + public T load(Type type, Object o, ConfigLoader configLoader) throws LoadException { + T obj = get((String) o); + if(obj == null) + throw new LoadException("No such " + type.getTypeName() + " matching \"" + o + "\" was found in this registry."); + return obj; + } + + /** + * Add a value to this registry. + * + * @param identifier Identifier to assign value. + * @param value Value to add. + */ + public boolean add(String identifier, T value) { + boolean exists = objects.containsKey(identifier); + objects.put(identifier, value); + return exists; + } + + /** + * Add a value to this registry, checking whether it is present first. + * + * @param identifier Identifier to assign value. + * @param value Value to add. + * @throws DuplicateEntryException If an entry with the same identifier is already present. + */ + public void addChecked(String identifier, T value) throws DuplicateEntryException { + if(objects.containsKey(identifier)) + throw new DuplicateEntryException("Value with identifier \"" + identifier + "\" is already defined in registry."); + add(identifier, value); + } + + @Override + public boolean contains(String identifier) { + return objects.containsKey(identifier); + } + + @Override + public T get(String identifier) { + return objects.get(identifier); + } + + @Override + public void forEach(Consumer consumer) { + objects.forEach((id, obj) -> consumer.accept(obj)); + } + + @Override + public void forEach(BiConsumer consumer) { + objects.forEach(consumer); + } + + @Override + public Set entries() { + return new HashSet<>(objects.values()); + } + + @Override + public Set keys() { + return objects.keySet(); + } + + /** + * Clears all entries from the registry. + */ + public void clear() { + objects.clear(); + } +} diff --git a/common/src/main/java/com/dfsek/terra/registry/TerraRegistry.java b/common/src/main/java/com/dfsek/terra/registry/TerraRegistry.java deleted file mode 100644 index 5b25ca67d..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/TerraRegistry.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.dfsek.terra.registry; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; - -import java.lang.reflect.Type; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -public abstract class TerraRegistry implements TypeLoader { - private final Map objects = new HashMap<>(); - - @Override - public T load(Type type, Object o, ConfigLoader configLoader) throws LoadException { - T obj = get((String) o); - if(obj == null) - throw new LoadException("No such " + type.getTypeName() + " matching \"" + o + "\" was found in this registry."); - return obj; - } - - /** - * Add an object to the registry with a name. - * - * @param name Name of the tree. - * @param value Object to increment - * @return True if tree was overwritten. - */ - public boolean add(String name, T value) { - boolean exists = objects.containsKey(name); - objects.put(name, value); - return exists; - } - - /** - * Check if the registry contains an object. - * - * @param name Name of the object. - * @return Whether the registry contains the object. - */ - public boolean contains(String name) { - return objects.containsKey(name); - } - - /** - * Get an object from the registry, - * - * @param id ID of object to get - * @return Object - */ - public T get(String id) { - return objects.get(id); - } - - public void forEach(Consumer consumer) { - objects.forEach((id, obj) -> consumer.accept(obj)); - } - - public void forEach(BiConsumer consumer) { - objects.forEach(consumer); - } - - public Set entries() { - return new HashSet<>(objects.values()); - } - - /** - * Clears all entries from the registry. - */ - public void clear() { - objects.clear(); - } -} diff --git a/common/src/main/java/com/dfsek/terra/registry/config/BiomeRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/BiomeRegistry.java index 06aad4412..5ad1d32a6 100644 --- a/common/src/main/java/com/dfsek/terra/registry/config/BiomeRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/BiomeRegistry.java @@ -2,16 +2,16 @@ package com.dfsek.terra.registry.config; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.registry.TerraRegistry; +import com.dfsek.terra.config.builder.BiomeBuilder; +import com.dfsek.terra.registry.OpenRegistry; import java.lang.reflect.Type; -public class BiomeRegistry extends TerraRegistry { +public class BiomeRegistry extends OpenRegistry { @Override - public TerraBiome load(Type type, Object o, ConfigLoader configLoader) throws LoadException { + public BiomeBuilder load(Type type, Object o, ConfigLoader configLoader) throws LoadException { if(o.equals("SELF")) return null; - TerraBiome biome = get((String) o); + BiomeBuilder biome = get((String) o); if(biome == null) throw new LoadException("No such " + type.getTypeName() + " matching \"" + o + "\" was found in this registry."); return biome; diff --git a/common/src/main/java/com/dfsek/terra/registry/config/CarverRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/CarverRegistry.java index 46fe3d725..63b80f715 100644 --- a/common/src/main/java/com/dfsek/terra/registry/config/CarverRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/CarverRegistry.java @@ -1,7 +1,7 @@ package com.dfsek.terra.registry.config; import com.dfsek.terra.carving.UserDefinedCarver; -import com.dfsek.terra.registry.TerraRegistry; +import com.dfsek.terra.registry.OpenRegistry; -public class CarverRegistry extends TerraRegistry { +public class CarverRegistry extends OpenRegistry { } diff --git a/common/src/main/java/com/dfsek/terra/registry/config/FloraRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/FloraRegistry.java index e62f88b08..71fd680cd 100644 --- a/common/src/main/java/com/dfsek/terra/registry/config/FloraRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/FloraRegistry.java @@ -1,18 +1,17 @@ package com.dfsek.terra.registry.config; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.world.flora.Flora; -import com.dfsek.terra.registry.TerraRegistry; -import com.dfsek.terra.util.MaterialSet; +import com.dfsek.terra.registry.OpenRegistry; import com.dfsek.terra.world.population.items.flora.ConstantFlora; import java.util.Arrays; import java.util.Collections; import java.util.concurrent.Callable; -public class FloraRegistry extends TerraRegistry { +public class FloraRegistry extends OpenRegistry { private final TerraPlugin main; public FloraRegistry(TerraPlugin main) { @@ -52,15 +51,15 @@ public class FloraRegistry extends TerraRegistry { addItem("BROWN_MUSHROOM", () -> new ConstantFlora(mushroom, Collections.singletonList(data("minecraft:brown_mushroom")))); } - private MaterialData create(String s) { - return main.getWorldHandle().createMaterialData(s); + private BlockData create(String s) { + return main.getWorldHandle().createBlockData(s); } private void addItem(String id, Callable flora) { try { add(id, flora.call()); } catch(Exception e) { - main.getLogger().warning("Failed to load Flora item: " + id + ": " + e.getMessage()); + main.logger().warning("Failed to load Flora item: " + id + ": " + e.getMessage()); } } @@ -70,7 +69,7 @@ public class FloraRegistry extends TerraRegistry { @Override - public Flora get(String id) { - return super.get(id); + public Flora get(String identifier) { + return super.get(identifier); } } diff --git a/common/src/main/java/com/dfsek/terra/registry/config/FunctionRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/FunctionRegistry.java new file mode 100644 index 000000000..2d140137a --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/registry/config/FunctionRegistry.java @@ -0,0 +1,7 @@ +package com.dfsek.terra.registry.config; + +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.registry.OpenRegistry; + +public class FunctionRegistry extends OpenRegistry> { +} diff --git a/common/src/main/java/com/dfsek/terra/registry/config/LootRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/LootRegistry.java index 21358ea41..8c8e987aa 100644 --- a/common/src/main/java/com/dfsek/terra/registry/config/LootRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/LootRegistry.java @@ -1,7 +1,7 @@ package com.dfsek.terra.registry.config; import com.dfsek.terra.api.structures.loot.LootTable; -import com.dfsek.terra.registry.TerraRegistry; +import com.dfsek.terra.registry.OpenRegistry; -public class LootRegistry extends TerraRegistry { +public class LootRegistry extends OpenRegistry { } diff --git a/common/src/main/java/com/dfsek/terra/registry/config/NoiseRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/NoiseRegistry.java index e6625b3e9..ccbfee9ca 100644 --- a/common/src/main/java/com/dfsek/terra/registry/config/NoiseRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/NoiseRegistry.java @@ -6,6 +6,7 @@ import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler; import com.dfsek.terra.api.math.noise.samplers.noise.simplex.OpenSimplex2SSampler; import com.dfsek.terra.api.math.noise.samplers.noise.simplex.OpenSimplex2Sampler; import com.dfsek.terra.api.math.noise.samplers.noise.simplex.PerlinSampler; +import com.dfsek.terra.api.math.noise.samplers.noise.simplex.SimplexSampler; import com.dfsek.terra.api.math.noise.samplers.noise.value.ValueCubicSampler; import com.dfsek.terra.api.math.noise.samplers.noise.value.ValueSampler; import com.dfsek.terra.api.util.seeded.NoiseSeeded; @@ -15,6 +16,7 @@ import com.dfsek.terra.config.loaders.config.sampler.templates.KernelTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.noise.CellularNoiseTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.noise.ConstantNoiseTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.noise.ExpressionFunctionTemplate; +import com.dfsek.terra.config.loaders.config.sampler.templates.noise.GaborNoiseTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.noise.SimpleNoiseTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.noise.fractal.BrownianMotionTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.noise.fractal.PingPongTemplate; @@ -22,11 +24,11 @@ import com.dfsek.terra.config.loaders.config.sampler.templates.noise.fractal.Rid import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.ClampNormalizerTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.LinearNormalizerTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.NormalNormalizerTemplate; -import com.dfsek.terra.registry.TerraRegistry; +import com.dfsek.terra.registry.OpenRegistry; import java.util.function.Supplier; -public class NoiseRegistry extends TerraRegistry>> { +public class NoiseRegistry extends OpenRegistry>> { public NoiseRegistry() { add("LINEAR", LinearNormalizerTemplate::new); add("NORMAL", NormalNormalizerTemplate::new); @@ -44,6 +46,8 @@ public class NoiseRegistry extends TerraRegistry new SimpleNoiseTemplate(OpenSimplex2Sampler::new)); add("OPENSIMPLEX2S", () -> new SimpleNoiseTemplate(OpenSimplex2SSampler::new)); add("PERLIN", () -> new SimpleNoiseTemplate(PerlinSampler::new)); + add("SIMPLEX", () -> new SimpleNoiseTemplate(SimplexSampler::new)); + add("GABOR", GaborNoiseTemplate::new); add("VALUE", () -> new SimpleNoiseTemplate(ValueSampler::new)); diff --git a/common/src/main/java/com/dfsek/terra/registry/config/OreRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/OreRegistry.java index 3f8e285df..010a812f2 100644 --- a/common/src/main/java/com/dfsek/terra/registry/config/OreRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/OreRegistry.java @@ -1,7 +1,7 @@ package com.dfsek.terra.registry.config; -import com.dfsek.terra.registry.TerraRegistry; +import com.dfsek.terra.registry.OpenRegistry; import com.dfsek.terra.world.population.items.ores.Ore; -public class OreRegistry extends TerraRegistry { +public class OreRegistry extends OpenRegistry { } diff --git a/common/src/main/java/com/dfsek/terra/registry/config/PaletteRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/PaletteRegistry.java index 2a8cb5704..e54c8ec81 100644 --- a/common/src/main/java/com/dfsek/terra/registry/config/PaletteRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/PaletteRegistry.java @@ -1,12 +1,12 @@ package com.dfsek.terra.registry.config; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.palette.SinglePalette; -import com.dfsek.terra.registry.TerraRegistry; +import com.dfsek.terra.registry.OpenRegistry; -public class PaletteRegistry extends TerraRegistry> { +public class PaletteRegistry extends OpenRegistry> { private final TerraPlugin main; public PaletteRegistry(TerraPlugin main) { this.main = main; @@ -14,9 +14,9 @@ public class PaletteRegistry extends TerraRegistry> { @Override - public Palette get(String id) { - if(id.startsWith("BLOCK:")) - return new SinglePalette<>(main.getWorldHandle().createBlockData(id.substring(6))); // Return single palette for BLOCK: shortcut. - return super.get(id); + public Palette get(String identifier) { + if(identifier.startsWith("BLOCK:")) + return new SinglePalette<>(main.getWorldHandle().createBlockData(identifier.substring(6))); // Return single palette for BLOCK: shortcut. + return super.get(identifier); } } diff --git a/common/src/main/java/com/dfsek/terra/registry/config/ScriptRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/ScriptRegistry.java index d4320f854..a715c5ad9 100644 --- a/common/src/main/java/com/dfsek/terra/registry/config/ScriptRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/ScriptRegistry.java @@ -1,7 +1,7 @@ package com.dfsek.terra.registry.config; import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.registry.TerraRegistry; +import com.dfsek.terra.registry.OpenRegistry; -public class ScriptRegistry extends TerraRegistry { +public class ScriptRegistry extends OpenRegistry { } diff --git a/common/src/main/java/com/dfsek/terra/registry/config/StructureRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/StructureRegistry.java index 523395fa7..56a24711d 100644 --- a/common/src/main/java/com/dfsek/terra/registry/config/StructureRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/StructureRegistry.java @@ -1,7 +1,7 @@ package com.dfsek.terra.registry.config; -import com.dfsek.terra.registry.TerraRegistry; +import com.dfsek.terra.registry.OpenRegistry; import com.dfsek.terra.world.population.items.TerraStructure; -public class StructureRegistry extends TerraRegistry { +public class StructureRegistry extends OpenRegistry { } diff --git a/common/src/main/java/com/dfsek/terra/registry/config/TreeRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/TreeRegistry.java index 82ac69fc6..b786c64f4 100644 --- a/common/src/main/java/com/dfsek/terra/registry/config/TreeRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/TreeRegistry.java @@ -1,9 +1,9 @@ package com.dfsek.terra.registry.config; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.world.tree.Tree; import com.dfsek.terra.api.world.tree.fractal.FractalTree; import com.dfsek.terra.api.world.tree.fractal.trees.Cactus; @@ -14,14 +14,13 @@ import com.dfsek.terra.api.world.tree.fractal.trees.ShatteredTree; import com.dfsek.terra.api.world.tree.fractal.trees.SmallShatteredPillar; import com.dfsek.terra.api.world.tree.fractal.trees.SmallShatteredTree; import com.dfsek.terra.api.world.tree.fractal.trees.SpruceTree; -import com.dfsek.terra.registry.TerraRegistry; +import com.dfsek.terra.registry.OpenRegistry; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Random; -import java.util.Set; -public class TreeRegistry extends TerraRegistry { +public class TreeRegistry extends OpenRegistry { private final TerraPlugin main; public TreeRegistry(TerraPlugin main) { @@ -40,13 +39,13 @@ public class TreeRegistry extends TerraRegistry { try { add(id, new FractalTreeHolder(value)); } catch(Exception e) { - main.getLogger().warning("Unable to load tree " + id + ": " + e.getMessage()); + main.logger().warning("Unable to load tree " + id + ": " + e.getMessage()); } } @Override - public boolean add(String name, Tree value) { - return super.add(name, value); + public boolean add(String identifier, Tree value) { + return super.add(identifier, value); } private final class FractalTreeHolder implements Tree { @@ -71,7 +70,7 @@ public class TreeRegistry extends TerraRegistry { } @Override - public Set getSpawnable() { + public MaterialSet getSpawnable() { return tree.getSpawnable(); } } diff --git a/common/src/main/java/com/dfsek/terra/registry/exception/DuplicateEntryException.java b/common/src/main/java/com/dfsek/terra/registry/exception/DuplicateEntryException.java new file mode 100644 index 000000000..477c93f50 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/registry/exception/DuplicateEntryException.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.registry.exception; + +/** + * Thrown when a duplicate entry is found in a registry. + */ +public class DuplicateEntryException extends Exception { + private static final long serialVersionUID = -7199021672428288780L; + + public DuplicateEntryException(String message) { + super(message); + } + + public DuplicateEntryException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/registry/master/AddonRegistry.java b/common/src/main/java/com/dfsek/terra/registry/master/AddonRegistry.java new file mode 100644 index 000000000..f2c50acfb --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/registry/master/AddonRegistry.java @@ -0,0 +1,110 @@ +package com.dfsek.terra.registry.master; + +import com.dfsek.terra.addon.AddonClassLoader; +import com.dfsek.terra.addon.AddonPool; +import com.dfsek.terra.addon.PreLoadAddon; +import com.dfsek.terra.addon.exception.AddonLoadException; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.addons.TerraAddon; +import com.dfsek.terra.api.injection.Injector; +import com.dfsek.terra.api.injection.exception.InjectionException; +import com.dfsek.terra.registry.OpenRegistry; +import com.dfsek.terra.registry.exception.DuplicateEntryException; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.logging.LogManager; +import java.util.logging.Logger; + +public class AddonRegistry extends OpenRegistry { + private final TerraPlugin main; + + public AddonRegistry(TerraPlugin main) { + + this.main = main; + } + + public AddonRegistry(TerraAddon addon, TerraPlugin main) { + this.main = main; + add(addon.getName(), addon); + } + + @Override + public boolean add(String identifier, TerraAddon addon) { + if(contains(identifier)) throw new IllegalArgumentException("Addon " + identifier + " is already registered."); + addon.initialize(); + main.logger().info("Loaded addon " + addon.getName() + " v" + addon.getVersion() + ", by " + addon.getAuthor()); + return super.add(identifier, addon); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + public boolean loadAll() { + Injector pluginInjector = new Injector<>(main); + pluginInjector.addExplicitTarget(TerraPlugin.class); + + boolean valid = true; + File addonsFolder = new File(main.getDataFolder(), "addons"); + addonsFolder.mkdirs(); + + AddonPool pool = new AddonPool(); + + try { + for(File jar : addonsFolder.listFiles(file -> file.getName().endsWith(".jar"))) { + main.logger().info("Loading Addon(s) from: " + jar.getName()); + for(Class addonClass : AddonClassLoader.fetchAddonClasses(jar)) { + pool.add(new PreLoadAddon(addonClass, jar)); + } + } + + pool.buildAll(); + + for(PreLoadAddon addon : pool.getAddons()) { + Class addonClass = addon.getAddonClass(); + Constructor constructor; + + String logPrefix = "Terra:" + addon.getId(); + Logger addonLogger = Logger.getLogger(logPrefix); + + if(!LogManager.getLogManager().addLogger(addonLogger)) { + addonLogger = LogManager.getLogManager().getLogger(logPrefix); + } + + Injector loggerInjector = new Injector<>(addonLogger); + loggerInjector.addExplicitTarget(Logger.class); + + try { + constructor = addonClass.getConstructor(); + } catch(NoSuchMethodException e) { + throw new AddonLoadException("Addon class has no valid constructor: " + addonClass.getCanonicalName(), e); + } + TerraAddon loadedAddon; + try { + loadedAddon = constructor.newInstance(); + pluginInjector.inject(loadedAddon); + loggerInjector.inject(loadedAddon); + } catch(InstantiationException | IllegalAccessException | InvocationTargetException | InjectionException e) { + throw new AddonLoadException("Failed to load addon \" + " + addon.getId() + "\": ", e); + } + try { + addChecked(loadedAddon.getName(), loadedAddon); + } catch(DuplicateEntryException e) { + valid = false; + main.logger().severe("Duplicate addon ID; addon with ID " + loadedAddon.getName() + " is already loaded."); + main.logger().severe("Existing addon class: " + get(loadedAddon.getName()).getClass().getCanonicalName()); + main.logger().severe("Duplicate addon class: " + addonClass.getCanonicalName()); + } + } + } catch(AddonLoadException | IOException e) { + e.printStackTrace(); + valid = false; + } + + return valid; + } +} diff --git a/common/src/main/java/com/dfsek/terra/registry/ConfigRegistry.java b/common/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java similarity index 84% rename from common/src/main/java/com/dfsek/terra/registry/ConfigRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java index 4f2dd1dd9..c756a2b2b 100644 --- a/common/src/main/java/com/dfsek/terra/registry/ConfigRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java @@ -1,8 +1,9 @@ -package com.dfsek.terra.registry; +package com.dfsek.terra.registry.master; import com.dfsek.tectonic.exception.ConfigException; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.registry.OpenRegistry; import java.io.File; import java.io.IOException; @@ -11,7 +12,7 @@ import java.util.zip.ZipFile; /** * Class to hold config packs */ -public class ConfigRegistry extends TerraRegistry { +public class ConfigRegistry extends OpenRegistry { public void load(File folder, TerraPlugin main) throws ConfigException { ConfigPack pack = new ConfigPack(folder, main); add(pack.getTemplate().getID(), pack); @@ -29,7 +30,7 @@ public class ConfigRegistry extends TerraRegistry { valid = false; } } - for(File zip : packsFolder.listFiles(file -> file.getName().endsWith(".zip") || file.getName().endsWith(".jar") || file.getName().endsWith(".com.dfsek.terra"))) { + for(File zip : packsFolder.listFiles(file -> file.getName().endsWith(".zip") || file.getName().endsWith(".terra"))) { try { main.getDebugLogger().info("Loading ZIP archive: " + zip.getName()); load(new ZipFile(zip), main); diff --git a/common/src/main/java/com/dfsek/terra/util/MaterialSet.java b/common/src/main/java/com/dfsek/terra/util/MaterialSet.java deleted file mode 100644 index 455051d97..000000000 --- a/common/src/main/java/com/dfsek/terra/util/MaterialSet.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dfsek.terra.util; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; - -import java.util.Arrays; -import java.util.HashSet; - -public class MaterialSet extends HashSet { - private static final long serialVersionUID = 3056512763631017301L; - - public static MaterialSet singleton(MaterialData material) { - MaterialSet set = new MaterialSet(); - set.add(material); - return set; - } - - public static MaterialSet get(MaterialData... materials) { - MaterialSet set = new MaterialSet(); - set.addAll(Arrays.asList(materials)); - return set; - } - - private void add(BlockData data) { - add(data.getMaterial()); - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/TerraWorld.java b/common/src/main/java/com/dfsek/terra/world/TerraWorld.java index e9442141a..d173d12f2 100644 --- a/common/src/main/java/com/dfsek/terra/world/TerraWorld.java +++ b/common/src/main/java/com/dfsek/terra/world/TerraWorld.java @@ -1,23 +1,25 @@ package com.dfsek.terra.world; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.api.core.event.events.world.TerraWorldLoadEvent; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.event.events.world.TerraWorldLoadEvent; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.generation.TerraChunkGenerator; import com.dfsek.terra.api.world.palette.Palette; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.biome.provider.BiomeProvider; import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.config.pack.WorldConfig; import com.dfsek.terra.profiler.WorldProfiler; -import com.dfsek.terra.world.generation.math.Sampler; +import com.dfsek.terra.world.generation.math.samplers.Sampler; import net.jafama.FastMath; public class TerraWorld { private final BiomeProvider provider; - private final ConfigPack config; + private final WorldConfig config; private final boolean safe; private final WorldProfiler profiler; private final World world; @@ -25,29 +27,33 @@ public class TerraWorld { public TerraWorld(World w, ConfigPack c, TerraPlugin main) { - c.getBiomeRegistry().forEach(biome -> biome.getGenerator(w)); // Load all gens to cache - config = c; - profiler = new WorldProfiler(w); - this.provider = config.getBiomeProviderBuilder().build(w.getSeed()); + if(!isTerraWorld(w)) throw new IllegalArgumentException("World " + w + " is not a Terra World!"); this.world = w; + config = c.toWorldConfig(this); + this.provider = config.getProvider(); + profiler = new WorldProfiler(w); air = main.getWorldHandle().createBlockData("minecraft:air"); main.getEventManager().callEvent(new TerraWorldLoadEvent(this)); safe = true; } - public World getWorld() { - return world; - } - public static boolean isTerraWorld(World w) { return w.getGenerator().getHandle() instanceof GeneratorWrapper; } + public World getWorld() { + return world; + } + + public TerraChunkGenerator getGenerator() { + return ((GeneratorWrapper) world.getGenerator().getHandle()).getHandle(); + } + public BiomeProvider getBiomeProvider() { return provider; } - public ConfigPack getConfig() { + public WorldConfig getConfig() { return config; } @@ -70,7 +76,7 @@ public class TerraWorld { public BlockData getUngeneratedBlock(int x, int y, int z) { UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome(x, z); Palette palette = biome.getGenerator(world).getPalette(y); - Sampler sampler = config.getSamplerCache().get(world, x, z); + Sampler sampler = config.getSamplerCache().get(x, z); int fdX = FastMath.floorMod(x, 16); int fdZ = FastMath.floorMod(z, 16); double noise = sampler.sample(fdX, y, fdZ); diff --git a/common/src/main/java/com/dfsek/terra/world/carving/NoiseCarver.java b/common/src/main/java/com/dfsek/terra/world/carving/NoiseCarver.java index 1fdf39c6b..e325e7a0c 100644 --- a/common/src/main/java/com/dfsek/terra/world/carving/NoiseCarver.java +++ b/common/src/main/java/com/dfsek/terra/world/carving/NoiseCarver.java @@ -1,13 +1,13 @@ package com.dfsek.terra.world.carving; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.world.ChunkAccess; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.world.Carver; -import com.dfsek.terra.world.generation.math.interpolation.BiomeChunkInterpolator; import com.dfsek.terra.world.generation.math.interpolation.ChunkInterpolator; +import com.dfsek.terra.world.generation.math.interpolation.ChunkInterpolator3D; public class NoiseCarver implements Carver { private final Range range; @@ -22,7 +22,7 @@ public class NoiseCarver implements Carver { @Override public void carve(World world, int chunkX, int chunkZ, ChunkAccess chunk) { - ChunkInterpolator interpolator = new BiomeChunkInterpolator(world, chunkX, chunkZ, main.getWorld(world).getBiomeProvider(), (gen, coord) -> gen.getCarver().getNoise(coord.setY(coord.getY()))); + ChunkInterpolator interpolator = new ChunkInterpolator3D(world, chunkX, chunkZ, main.getWorld(world).getBiomeProvider(), (gen, coord) -> gen.getCarver().getNoise(coord.setY(coord.getY()))); for(int y : range) { for(int x = 0; x < 16; x++) { for(int z = 0; z < 16; z++) { diff --git a/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator2D.java b/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator2D.java new file mode 100644 index 000000000..ed93986bc --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator2D.java @@ -0,0 +1,128 @@ +package com.dfsek.terra.world.generation.generators; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.math.Range; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.world.BiomeGrid; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.platform.world.generator.ChunkData; +import com.dfsek.terra.api.util.world.PaletteUtil; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.generation.TerraChunkGenerator; +import com.dfsek.terra.api.world.palette.Palette; +import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.config.templates.BiomeTemplate; +import com.dfsek.terra.profiler.ProfileFuture; +import com.dfsek.terra.world.Carver; +import com.dfsek.terra.world.TerraWorld; +import com.dfsek.terra.world.carving.NoiseCarver; +import com.dfsek.terra.world.generation.math.SamplerCache; +import com.dfsek.terra.world.generation.math.samplers.Sampler; +import com.dfsek.terra.world.generation.math.samplers.Sampler2D; +import net.jafama.FastMath; +import org.jetbrains.annotations.NotNull; + +import java.util.Random; + +public class DefaultChunkGenerator2D implements TerraChunkGenerator { + private final ConfigPack configPack; + private final TerraPlugin main; + + private final Carver carver; + + private final SamplerCache cache; + + public DefaultChunkGenerator2D(ConfigPack c, TerraPlugin main, SamplerCache cache) { + this.configPack = c; + this.main = main; + carver = new NoiseCarver(new Range(0, 255), main.getWorldHandle().createBlockData("minecraft:air"), main); + this.cache = cache; + } + + @Override + public boolean isParallelCapable() { + return true; + } + + @Override + public boolean shouldGenerateCaves() { + return configPack.getTemplate().vanillaCaves(); + } + + @Override + public boolean shouldGenerateDecorations() { + return configPack.getTemplate().vanillaDecorations(); + } + + @Override + public boolean shouldGenerateMobs() { + return configPack.getTemplate().vanillaMobs(); + } + + @Override + public boolean shouldGenerateStructures() { + return configPack.getTemplate().vanillaStructures(); + } + + @Override + public ConfigPack getConfigPack() { + return configPack; + } + + @Override + public TerraPlugin getMain() { + return main; + } + + @Override + @SuppressWarnings({"try"}) + public ChunkData generateChunkData(@NotNull World world, Random random, int chunkX, int chunkZ, ChunkData chunk) { + TerraWorld tw = main.getWorld(world); + BiomeProvider grid = tw.getBiomeProvider(); + try(ProfileFuture ignore = tw.getProfiler().measure("TotalChunkGenTime")) { + if(!tw.isSafe()) return chunk; + int xOrig = (chunkX << 4); + int zOrig = (chunkZ << 4); + + Sampler sampler = cache.getChunk(chunkX, chunkZ); + + for(int x = 0; x < 16; x++) { + for(int z = 0; z < 16; z++) { + int paletteLevel = 0; + int seaPaletteLevel = 0; + + int cx = xOrig + x; + int cz = zOrig + z; + + TerraBiome b = grid.getBiome(xOrig + x, zOrig + z); + BiomeTemplate c = ((UserDefinedBiome) b).getConfig(); + + Palette seaPalette = c.getOceanPalette(); + + int height = FastMath.min((int) sampler.sample(x, 0, z), world.getMaxHeight() - 1); + + for(int y = FastMath.max(height, c.getSeaLevel()); y >= 0; y--) { + BlockData data = y > height ? seaPalette.get(seaPaletteLevel++, cx, y, cz) : PaletteUtil.getPalette(x, y, z, c, sampler).get(paletteLevel++, cx, y, cz); + chunk.setBlock(x, y, z, data); + } + } + } + if(configPack.getTemplate().doBetaCarvers()) { + carver.carve(world, chunkX, chunkZ, chunk); + } + return chunk; + } + } + + @Override + public void generateBiomes(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, @NotNull BiomeGrid biome) { + DefaultChunkGenerator3D.biomes(world, chunkX, chunkZ, biome, main); + } + + @Override + public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) { + return new Sampler2D(chunkX, chunkZ, provider, world, elevationSmooth); + } +} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/MasterChunkGenerator.java b/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator3D.java similarity index 72% rename from common/src/main/java/com/dfsek/terra/world/generation/MasterChunkGenerator.java rename to common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator3D.java index 4f74ccdb4..af656ac84 100644 --- a/common/src/main/java/com/dfsek/terra/world/generation/MasterChunkGenerator.java +++ b/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator3D.java @@ -1,58 +1,54 @@ -package com.dfsek.terra.world.generation; +package com.dfsek.terra.world.generation.generators; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.block.BlockType; import com.dfsek.terra.api.platform.block.data.Bisected; import com.dfsek.terra.api.platform.block.data.Slab; import com.dfsek.terra.api.platform.block.data.Stairs; import com.dfsek.terra.api.platform.block.data.Waterlogged; import com.dfsek.terra.api.platform.world.BiomeGrid; import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.generator.ChunkData; +import com.dfsek.terra.api.util.world.PaletteUtil; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.api.world.generation.TerraChunkGenerator; import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.palette.SinglePalette; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.biome.provider.BiomeProvider; import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.templates.BiomeTemplate; import com.dfsek.terra.profiler.ProfileFuture; -import com.dfsek.terra.util.PaletteUtil; import com.dfsek.terra.world.Carver; import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.carving.NoiseCarver; -import com.dfsek.terra.world.generation.math.Sampler; -import com.dfsek.terra.world.generation.math.SamplerCache; +import com.dfsek.terra.world.generation.math.samplers.Sampler; +import com.dfsek.terra.world.generation.math.samplers.Sampler3D; import org.jetbrains.annotations.NotNull; import java.util.Map; import java.util.Random; -public class MasterChunkGenerator implements TerraChunkGenerator { - - +public class DefaultChunkGenerator3D implements TerraChunkGenerator { private final ConfigPack configPack; private final TerraPlugin main; - private final MaterialData water; + private final BlockType water; private final SinglePalette blank; private final Carver carver; - private final SamplerCache cache; - public MasterChunkGenerator(ConfigPack c, TerraPlugin main, SamplerCache cache) { + public DefaultChunkGenerator3D(ConfigPack c, TerraPlugin main) { this.configPack = c; this.main = main; carver = new NoiseCarver(new Range(0, 255), main.getWorldHandle().createBlockData("minecraft:air"), main); - water = main.getWorldHandle().createMaterialData("minecraft:water"); + water = main.getWorldHandle().createBlockData("minecraft:water").getBlockType(); blank = new SinglePalette<>(main.getWorldHandle().createBlockData("minecraft:air")); - this.cache = cache; } @Override @@ -92,7 +88,7 @@ public class MasterChunkGenerator implements TerraChunkGenerator { @Override @SuppressWarnings({"try"}) - public ChunkGenerator.ChunkData generateChunkData(@NotNull World world, Random random, int chunkX, int chunkZ, ChunkGenerator.ChunkData chunk) { + public ChunkData generateChunkData(@NotNull World world, Random random, int chunkX, int chunkZ, ChunkData chunk) { TerraWorld tw = main.getWorld(world); BiomeProvider grid = tw.getBiomeProvider(); try(ProfileFuture ignore = tw.getProfiler().measure("TotalChunkGenTime")) { @@ -100,10 +96,10 @@ public class MasterChunkGenerator implements TerraChunkGenerator { int xOrig = (chunkX << 4); int zOrig = (chunkZ << 4); - Sampler sampler = cache.getChunk(world, chunkX, chunkZ); + Sampler sampler = tw.getConfig().getSamplerCache().getChunk(chunkX, chunkZ); - for(byte x = 0; x < 16; x++) { - for(byte z = 0; z < 16; z++) { + for(int x = 0; x < 16; x++) { + for(int z = 0; z < 16; z++) { int paletteLevel = 0; int cx = xOrig + x; @@ -117,7 +113,7 @@ public class MasterChunkGenerator implements TerraChunkGenerator { boolean justSet = false; BlockData data = null; - for(int y = world.getMaxHeight() - 1; y >= 0; y--) { + for(int y = world.getMaxHeight() - 1; y >= world.getMinHeight(); y--) { if(sampler.sample(x, y, z) > 0) { justSet = true; data = PaletteUtil.getPalette(x, y, z, c, sampler).get(paletteLevel, cx, y, cz); @@ -151,11 +147,11 @@ public class MasterChunkGenerator implements TerraChunkGenerator { } } - private void prepareBlockPartFloor(BlockData down, BlockData orig, ChunkGenerator.ChunkData chunk, Vector3 block, Map> slabs, - Map> stairs, double thresh, Sampler sampler) { + private void prepareBlockPartFloor(BlockData down, BlockData orig, ChunkData chunk, Vector3 block, Map> slabs, + Map> stairs, double thresh, Sampler sampler) { if(sampler.sample(block.getX(), block.getY() - 0.4, block.getZ()) > thresh) { if(stairs != null) { - Palette stairPalette = stairs.get(down.getMaterial()); + Palette stairPalette = stairs.get(down.getBlockType()); if(stairPalette != null) { BlockData stair = stairPalette.get(0, block.getX(), block.getY(), block.getZ()).clone(); if(stair instanceof Stairs) { @@ -164,19 +160,19 @@ public class MasterChunkGenerator implements TerraChunkGenerator { } } } - BlockData slab = slabs.getOrDefault(down.getMaterial(), blank).get(0, block.getX(), block.getY(), block.getZ()); + BlockData slab = slabs.getOrDefault(down.getBlockType(), blank).get(0, block.getX(), block.getY(), block.getZ()); if(slab instanceof Waterlogged) { - ((Waterlogged) slab).setWaterlogged(orig.matches(water)); - } else if(orig.matches(water)) return; + ((Waterlogged) slab).setWaterlogged(orig.getBlockType().equals(water)); + } else if(orig.getBlockType().equals(water)) return; chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), slab); } } - private void prepareBlockPartCeiling(BlockData up, BlockData orig, ChunkGenerator.ChunkData chunk, Vector3 block, Map> slabs, - Map> stairs, double thresh, Sampler sampler) { + private void prepareBlockPartCeiling(BlockData up, BlockData orig, ChunkData chunk, Vector3 block, Map> slabs, + Map> stairs, double thresh, Sampler sampler) { if(sampler.sample(block.getX(), block.getY() + 0.4, block.getZ()) > thresh) { if(stairs != null) { - Palette stairPalette = stairs.get(up.getMaterial()); + Palette stairPalette = stairs.get(up.getBlockType()); if(stairPalette != null) { BlockData stair = stairPalette.get(0, block.getX(), block.getY(), block.getZ()).clone(); if(stair instanceof Stairs) { @@ -186,17 +182,17 @@ public class MasterChunkGenerator implements TerraChunkGenerator { } } } - BlockData slab = slabs.getOrDefault(up.getMaterial(), blank).get(0, block.getX(), block.getY(), block.getZ()).clone(); + BlockData slab = slabs.getOrDefault(up.getBlockType(), blank).get(0, block.getX(), block.getY(), block.getZ()).clone(); if(slab instanceof Bisected) ((Bisected) slab).setHalf(Bisected.Half.TOP); if(slab instanceof Slab) ((Slab) slab).setType(Slab.Type.TOP); if(slab instanceof Waterlogged) { - ((Waterlogged) slab).setWaterlogged(orig.matches(water)); - } else if(orig.matches(water)) return; // Only replace water if waterlogged. + ((Waterlogged) slab).setWaterlogged(orig.getBlockType().equals(water)); + } else if(orig.getBlockType().equals(water)) return; // Only replace water if waterlogged. chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), slab); } } - private boolean placeStair(BlockData orig, ChunkGenerator.ChunkData chunk, Vector3 block, double thresh, Sampler sampler, Stairs stairNew) { + private boolean placeStair(BlockData orig, ChunkData chunk, Vector3 block, double thresh, Sampler sampler, Stairs stairNew) { if(sampler.sample(block.getBlockX() - 0.55, block.getY(), block.getZ()) > thresh) { @@ -209,30 +205,35 @@ public class MasterChunkGenerator implements TerraChunkGenerator { stairNew.setFacing(BlockFace.EAST); } else stairNew = null; if(stairNew != null) { - if(orig.matches(water)) stairNew.setWaterlogged(orig.matches(water)); + if(orig.getBlockType().equals(water)) stairNew.setWaterlogged(orig.getBlockType().equals(water)); chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), stairNew); return true; } return false; } - @Override - public void generateBiomes(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, @NotNull BiomeGrid biome) { + static void biomes(@NotNull World world, int chunkX, int chunkZ, @NotNull BiomeGrid biome, TerraPlugin main) { int xOrig = (chunkX << 4); int zOrig = (chunkZ << 4); BiomeProvider grid = main.getWorld(world).getBiomeProvider(); for(int x = 0; x < 4; x++) { - for(byte z = 0; z < 4; z++) { + for(int z = 0; z < 4; z++) { int cx = xOrig + (x << 2); int cz = zOrig + (z << 2); TerraBiome b = grid.getBiome(cx, cz); - biome.setBiome(x << 2, z << 2, b.getVanillaBiomes().get(b.getGenerator(world).getBiomeNoise(), cx, 0, cz)); + biome.setBiome(cx, cz, b.getVanillaBiomes().get(b.getGenerator(world).getBiomeNoise(), cx, 0, cz)); } } } - public SamplerCache getCache() { - return cache; + @Override + public void generateBiomes(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, @NotNull BiomeGrid biome) { + biomes(world, chunkX, chunkZ, biome, main); + } + + @Override + public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) { + return new Sampler3D(chunkX, chunkZ, provider, world, elevationSmooth); } } diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/Sampler.java b/common/src/main/java/com/dfsek/terra/world/generation/math/Sampler.java deleted file mode 100644 index 41de6b12d..000000000 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/Sampler.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dfsek.terra.world.generation.math; - -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.biome.provider.BiomeProvider; -import com.dfsek.terra.world.generation.math.interpolation.BiomeChunkInterpolator; -import com.dfsek.terra.world.generation.math.interpolation.ElevationInterpolator; -import net.jafama.FastMath; - -public class Sampler { - private final BiomeChunkInterpolator interpolator; - private final ElevationInterpolator elevationInterpolator; - - public Sampler(int x, int z, BiomeProvider provider, World world, int elevationSmooth) { - this.interpolator = new BiomeChunkInterpolator(world, x, z, provider, (generator, coord) -> generator.getBaseSampler().getNoise(coord)); - this.elevationInterpolator = new ElevationInterpolator(world, x, z, provider, elevationSmooth); - } - - public double sample(double x, double y, double z) { - return interpolator.getNoise(x, y, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z)); - } - - public static double noise2dExtrude(double y, double base) { - return ((-FastMath.pow2((y / base))) + 1); - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/SamplerCache.java b/common/src/main/java/com/dfsek/terra/world/generation/math/SamplerCache.java index 5bb3c58d6..64d4577b1 100644 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/SamplerCache.java +++ b/common/src/main/java/com/dfsek/terra/world/generation/math/SamplerCache.java @@ -1,9 +1,10 @@ package com.dfsek.terra.world.generation.math; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.MathUtil; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.world.TerraWorld; +import com.dfsek.terra.world.generation.math.samplers.Sampler; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; @@ -15,56 +16,33 @@ import java.util.HashMap; import java.util.Map; public class SamplerCache { - private final Map containerMap; - private final TerraPlugin main; + private final LoadingCache cache; - public SamplerCache(TerraPlugin main) { - containerMap = Collections.synchronizedMap(new HashMap<>()); - this.main = main; + public SamplerCache(TerraPlugin main, TerraWorld world) { + cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getSamplerCache()) + .build(new CacheLoader() { + @Override + public Sampler load(@NotNull Long key) { + int cx = (int) (key >> 32); + int cz = (int) key.longValue(); + return world.getGenerator().createSampler(cx, cz, world.getBiomeProvider(), world.getWorld(), world.getConfig().getTemplate().getElevationBlend()); + } + }); } - public Sampler get(World world, int x, int z) { - synchronized(containerMap) { - return containerMap.computeIfAbsent(world.getSeed(), seed -> new Container(world)).get(x, z); - } + public Sampler get(int x, int z) { + int cx = FastMath.floorDiv(x, 16); + int cz = FastMath.floorDiv(z, 16); + return getChunk(cx, cz); } - public Sampler getChunk(World world, int chunkX, int chunkZ) { - synchronized(containerMap) { - return containerMap.computeIfAbsent(world.getSeed(), seed -> new Container(world)).getChunk(chunkX, chunkZ); - } + public Sampler getChunk(int cx, int cz) { + long key = MathUtil.squash(cx, cz); + return cache.getUnchecked(key); } public void clear() { - containerMap.clear(); - } - - private class Container { - private final TerraWorld terraWorld; - private final LoadingCache cache; - - private Container(World world) { - cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getSamplerCache()) - .build(new CacheLoader() { - @Override - public Sampler load(@NotNull Long key) { - int cx = (int) (key >> 32); - int cz = (int) key.longValue(); - return new Sampler(cx, cz, terraWorld.getBiomeProvider(), world, terraWorld.getConfig().getTemplate().getElevationBlend()); - } - }); - terraWorld = main.getWorld(world); - } - - public Sampler get(int x, int z) { - int cx = FastMath.floorDiv(x, 16); - int cz = FastMath.floorDiv(z, 16); - return getChunk(cx, cz); - } - - public Sampler getChunk(int cx, int cz) { - long key = MathUtil.squash(cx, cz); - return cache.getUnchecked(key); - } + cache.invalidateAll(); + cache.cleanUp(); } } diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator.java b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator.java index 210d5c503..a17757c9f 100644 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator.java +++ b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator.java @@ -1,5 +1,10 @@ package com.dfsek.terra.world.generation.math.interpolation; +import com.dfsek.terra.api.util.mutable.MutableInteger; +import com.dfsek.terra.api.world.biome.Generator; + +import java.util.Map; + public interface ChunkInterpolator { /** * Gets the noise at a pair of internal chunk coordinates. @@ -9,4 +14,25 @@ public interface ChunkInterpolator { * @return double - The interpolated noise at the coordinates. */ double getNoise(double x, double y, double z); + + default double getNoise(int x, int y, int z) { // Floating-point modulus operations are expensive. This allows implementations to optionally handle integers separately. + return getNoise((double) x, y, z); + } + + + default double computeNoise(Map gens, double x, double y, double z) { + double n = 0; + double div = 0; + for(Map.Entry entry : gens.entrySet()) { + Generator gen = entry.getKey(); + int weight = entry.getValue().get(); + double noise = computeNoise(gen, x, y, z); + + n += noise * weight; + div += gen.getWeight() * weight; + } + return n / div; + } + + double computeNoise(Generator generator, double x, double y, double z); } diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator2D.java b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator2D.java new file mode 100644 index 000000000..27c0d42e7 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator2D.java @@ -0,0 +1,88 @@ +package com.dfsek.terra.world.generation.math.interpolation; + +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.util.mutable.MutableInteger; +import com.dfsek.terra.api.world.biome.Generator; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; +import net.jafama.FastMath; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiFunction; + +/** + * Class to abstract away the Interpolators needed to generate a chunk.
+ * Contains method to get interpolated noise at a coordinate within the chunk. + */ +public class ChunkInterpolator2D implements ChunkInterpolator { + private final Interpolator[][] interpGrid = new Interpolator[4][4]; + private final BiFunction noiseGetter; + + /** + * Instantiates a 3D ChunkInterpolator3D at a pair of chunk coordinates. + * + * @param chunkX X coordinate of the chunk. + * @param chunkZ Z coordinate of the chunk. + * @param provider Biome Provider to use for biome fetching. + */ + public ChunkInterpolator2D(World w, int chunkX, int chunkZ, BiomeProvider provider, BiFunction noiseGetter) { + this.noiseGetter = noiseGetter; + int xOrigin = chunkX << 4; + int zOrigin = chunkZ << 4; + + double[][] noiseStorage = new double[5][5]; + + for(int x = 0; x < 5; x++) { + for(int z = 0; z < 5; z++) { + Generator generator = provider.getBiome(xOrigin + (x << 2), zOrigin + (z << 2)).getGenerator(w); + Map genMap = new HashMap<>(); + + int step = generator.getBlendStep(); + int blend = generator.getBlendDistance(); + + for(int xi = -blend; xi <= blend; xi++) { + for(int zi = -blend; zi <= blend; zi++) { + genMap.computeIfAbsent(provider.getBiome(xOrigin + (x << 2) + (xi * step), zOrigin + (z << 2) + (zi * step)).getGenerator(w), g -> new MutableInteger(0)).increment(); // Increment by 1 + } + } + + noiseStorage[x][z] = computeNoise(genMap, (x << 2) + xOrigin, 0, (z << 2) + zOrigin); + } + } + + for(int x = 0; x < 4; x++) { + for(int z = 0; z < 4; z++) { + interpGrid[x][z] = new Interpolator( + noiseStorage[x][z], + noiseStorage[x + 1][z], + noiseStorage[x][z + 1], + noiseStorage[x + 1][z + 1]); + } + } + } + + private static int reRange(int value, int high) { + return FastMath.max(FastMath.min(value, high), 0); + } + + public double computeNoise(Generator generator, double x, double y, double z) { + return noiseGetter.apply(generator, new Vector3(x, y, z)); + } + + /** + * Gets the noise at a pair of internal chunk coordinates. + * + * @param x The internal X coordinate (0-15). + * @param z The internal Z coordinate (0-15). + * @return double - The interpolated noise at the coordinates. + */ + @Override + public double getNoise(double x, double y, double z) { + return interpGrid[reRange(((int) x) / 4, 3)][reRange(((int) z) / 4, 3)].bilerp((x % 4) / 4, (z % 4) / 4); + } + + public double getNoise(int x, int y, int z) { + return interpGrid[x / 4][z / 4].bilerp((double) (x % 4) / 4, (double) (z % 4) / 4); + } +} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/BiomeChunkInterpolator.java b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator3D.java similarity index 67% rename from common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/BiomeChunkInterpolator.java rename to common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator3D.java index fdb8fe31d..727a8e25e 100644 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/BiomeChunkInterpolator.java +++ b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator3D.java @@ -4,7 +4,7 @@ import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.util.mutable.MutableInteger; import com.dfsek.terra.api.world.biome.Generator; -import com.dfsek.terra.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import net.jafama.FastMath; import java.util.HashMap; @@ -15,23 +15,34 @@ import java.util.function.BiFunction; * Class to abstract away the Interpolators needed to generate a chunk.
* Contains method to get interpolated noise at a coordinate within the chunk. */ -public class BiomeChunkInterpolator implements ChunkInterpolator { - private final Interpolator3[][][] interpGrid = new Interpolator3[4][64][4]; +public class ChunkInterpolator3D implements ChunkInterpolator { + private final Interpolator3[][][] interpGrid; private final BiFunction noiseGetter; + private final int min; + private final int max; + /** - * Instantiates a 3D BiomeChunkInterpolator at a pair of chunk coordinates. + * Instantiates a 3D ChunkInterpolator3D at a pair of chunk coordinates. * * @param chunkX X coordinate of the chunk. * @param chunkZ Z coordinate of the chunk. * @param provider Biome Provider to use for biome fetching. */ - public BiomeChunkInterpolator(World w, int chunkX, int chunkZ, BiomeProvider provider, BiFunction noiseGetter) { + public ChunkInterpolator3D(World w, int chunkX, int chunkZ, BiomeProvider provider, BiFunction noiseGetter) { this.noiseGetter = noiseGetter; int xOrigin = chunkX << 4; int zOrigin = chunkZ << 4; - double[][][] noiseStorage = new double[5][5][65]; + this.max = w.getMaxHeight(); + this.min = w.getMinHeight(); + int range = max - min + 1; + + int size = range >> 2; + + interpGrid = new Interpolator3[4][size][4]; + + double[][][] noiseStorage = new double[5][5][size + 1]; for(int x = 0; x < 5; x++) { for(int z = 0; z < 5; z++) { @@ -47,15 +58,15 @@ public class BiomeChunkInterpolator implements ChunkInterpolator { } } - for(int y = 0; y < 65; y++) { + for(int y = 0; y < size + 1; y++) { noiseStorage[x][z][y] = computeNoise(genMap, (x << 2) + xOrigin, y << 2, (z << 2) + zOrigin); } } } - for(byte x = 0; x < 4; x++) { - for(byte z = 0; z < 4; z++) { - for(int y = 0; y < 64; y++) { + for(int x = 0; x < 4; x++) { + for(int z = 0; z < 4; z++) { + for(int y = 0; y < size; y++) { interpGrid[x][y][z] = new Interpolator3( noiseStorage[x][z][y], noiseStorage[x + 1][z][y], @@ -70,21 +81,7 @@ public class BiomeChunkInterpolator implements ChunkInterpolator { } } - private double computeNoise(Map gens, double x, double y, double z) { - double n = 0; - double div = 0; - for(Map.Entry entry : gens.entrySet()) { - Generator gen = entry.getKey(); - int weight = entry.getValue().get(); - double noise = computeNoise(gen, x, y, z); - - n += noise * weight; - div += gen.getWeight() * weight; - } - return n / div; - } - - private double computeNoise(Generator generator, double x, double y, double z) { + public double computeNoise(Generator generator, double x, double y, double z) { return noiseGetter.apply(generator, new Vector3(x, y, z)); } @@ -101,6 +98,10 @@ public class BiomeChunkInterpolator implements ChunkInterpolator { */ @Override public double getNoise(double x, double y, double z) { - return interpGrid[reRange(((int) x) / 4, 3)][reRange(((int) y) / 4, 63)][reRange(((int) z) / 4, 3)].trilerp((x % 4) / 4, (y % 4) / 4, (z % 4) / 4); + return interpGrid[reRange(((int) x) / 4, 3)][FastMath.max(FastMath.min(((int) y), max), min) / 4][reRange(((int) z) / 4, 3)].trilerp((x % 4) / 4, (y % 4) / 4, (z % 4) / 4); + } + + public double getNoise(int x, int y, int z) { + return interpGrid[x / 4][y / 4][z / 4].trilerp((double) (x % 4) / 4, (double) (y % 4) / 4, (double) (z % 4) / 4); } } diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ElevationInterpolator.java b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ElevationInterpolator.java index 5e2d05910..330cafdc8 100644 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ElevationInterpolator.java +++ b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ElevationInterpolator.java @@ -2,7 +2,7 @@ package com.dfsek.terra.world.generation.math.interpolation; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.world.biome.Generator; -import com.dfsek.terra.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.world.generation.WorldGenerator; public class ElevationInterpolator { diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/Interpolator.java b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/Interpolator.java index cc15c55aa..bf002e8a4 100644 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/Interpolator.java +++ b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/Interpolator.java @@ -31,7 +31,6 @@ public class Interpolator { */ public static double lerp(double t, double v0, double v1) { return v0 + t * (v1 - v0); - } /** diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/Interpolator3.java b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/Interpolator3.java index 6fd4c69a3..c7a7c0275 100644 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/Interpolator3.java +++ b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/Interpolator3.java @@ -4,7 +4,8 @@ package com.dfsek.terra.world.generation.math.interpolation; * Class for bilinear interpolation of values arranged on a unit square. */ public class Interpolator3 { - private final double _000, _100, _010, _110, _001, _101, _011, _111; + private final Interpolator bottom; + private final Interpolator top; /** * Constructs an interpolator with given values as vertices of a unit cube. @@ -18,21 +19,14 @@ public class Interpolator3 { * * @param _111 The value at (t, u, v) = (1, 1, 1). */ public Interpolator3(double _000, double _100, - double _010, double _110, double _001, double _101, + double _010, double _110, + double _001, double _101, double _011, double _111) { - this._000 = _000; - this._001 = _001; - this._010 = _010; - this._011 = _011; - this._100 = _100; - this._101 = _101; - this._110 = _110; - this._111 = _111; + this.top = new Interpolator(_000, _010, _001, _011); + this.bottom = new Interpolator(_100, _110, _101, _111); } public double trilerp(double x, double y, double z) { - Interpolator top = new Interpolator(_000, _010, _001, _011); - Interpolator bottom = new Interpolator(_100, _110, _101, _111); return Interpolator.lerp(x, top.bilerp(y, z), bottom.bilerp(y, z)); } } \ No newline at end of file diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/NoiseChunkInterpolator.java b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/NoiseChunkInterpolator.java deleted file mode 100644 index ec845d7ad..000000000 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/NoiseChunkInterpolator.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.dfsek.terra.world.generation.math.interpolation; - -import com.dfsek.terra.api.math.noise.NoiseSampler; -import net.jafama.FastMath; - -public class NoiseChunkInterpolator implements ChunkInterpolator { - private final Interpolator3[][][] interpGrid = new Interpolator3[4][64][4]; - - public NoiseChunkInterpolator(int chunkX, int chunkZ, NoiseSampler noise) { - int xOrigin = chunkX << 4; - int zOrigin = chunkZ << 4; - - double[][][] noiseStorage = new double[5][5][65]; - - for(int x = 0; x < 5; x++) { - for(int z = 0; z < 5; z++) { - for(int y = 0; y < 65; y++) { - noiseStorage[x][z][y] = noise.getNoise((x << 2) + xOrigin, y << 2, (z << 2) + zOrigin); - } - } - } - - for(byte x = 0; x < 4; x++) { - for(byte z = 0; z < 4; z++) { - for(int y = 0; y < 64; y++) { - interpGrid[x][y][z] = new Interpolator3( - noiseStorage[x][z][y], - noiseStorage[x + 1][z][y], - noiseStorage[x][z][y + 1], - noiseStorage[x + 1][z][y + 1], - noiseStorage[x][z + 1][y], - noiseStorage[x + 1][z + 1][y], - noiseStorage[x][z + 1][y + 1], - noiseStorage[x + 1][z + 1][y + 1]); - } - } - } - } - - private static int reRange(int value, int high) { - return FastMath.max(FastMath.min(value, high), 0); - } - - @Override - public double getNoise(double x, double y, double z) { - return interpGrid[reRange(((int) x) / 4, 3)][reRange(((int) y) / 4, 63)][reRange(((int) z) / 4, 3)].trilerp((x % 4) / 4, (y % 4) / 4, (z % 4) / 4); - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler.java b/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler.java new file mode 100644 index 000000000..d7dffcbe4 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler.java @@ -0,0 +1,10 @@ +package com.dfsek.terra.world.generation.math.samplers; + +@FunctionalInterface +public interface Sampler { + double sample(double x, double y, double z); + + default double sample(int x, int y, int z) { // Floating-point modulus operations are expensive. This allows implementations to optionally handle integers separately. + return sample((double) x, y, z); + } +} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler2D.java b/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler2D.java new file mode 100644 index 000000000..8b1b53bf7 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler2D.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.world.generation.math.samplers; + +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; +import com.dfsek.terra.world.generation.math.interpolation.ChunkInterpolator2D; +import com.dfsek.terra.world.generation.math.interpolation.ElevationInterpolator; +import net.jafama.FastMath; + +public class Sampler2D implements Sampler { + private final ChunkInterpolator2D interpolator; + private final ElevationInterpolator elevationInterpolator; + + public Sampler2D(int x, int z, BiomeProvider provider, World world, int elevationSmooth) { + this.interpolator = new ChunkInterpolator2D(world, x, z, provider, (generator, coord) -> generator.getBaseSampler().getNoise(coord)); + this.elevationInterpolator = new ElevationInterpolator(world, x, z, provider, elevationSmooth); + } + + @Override + public double sample(double x, double y, double z) { + return interpolator.getNoise(x, 0, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z)); + } + + @Override + public double sample(int x, int y, int z) { + return interpolator.getNoise(x, 0, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z)); + } +} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler3D.java b/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler3D.java new file mode 100644 index 000000000..6a6c085b6 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler3D.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.world.generation.math.samplers; + +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; +import com.dfsek.terra.world.generation.math.interpolation.ChunkInterpolator3D; +import com.dfsek.terra.world.generation.math.interpolation.ElevationInterpolator; +import net.jafama.FastMath; + +public class Sampler3D implements Sampler { + private final ChunkInterpolator3D interpolator; + private final ElevationInterpolator elevationInterpolator; + + public Sampler3D(int x, int z, BiomeProvider provider, World world, int elevationSmooth) { + this.interpolator = new ChunkInterpolator3D(world, x, z, provider, (generator, coord) -> generator.getBaseSampler().getNoise(coord)); + this.elevationInterpolator = new ElevationInterpolator(world, x, z, provider, elevationSmooth); + } + + @Override + public double sample(double x, double y, double z) { + return interpolator.getNoise(x, y, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z)); + } + + @Override + public double sample(int x, int y, int z) { + return interpolator.getNoise(x, y, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z)); + } +} diff --git a/common/src/main/java/com/dfsek/terra/population/CavePopulator.java b/common/src/main/java/com/dfsek/terra/world/population/CavePopulator.java similarity index 58% rename from common/src/main/java/com/dfsek/terra/population/CavePopulator.java rename to common/src/main/java/com/dfsek/terra/world/population/CavePopulator.java index 720918abe..15d386ca9 100644 --- a/common/src/main/java/com/dfsek/terra/population/CavePopulator.java +++ b/common/src/main/java/com/dfsek/terra/world/population/CavePopulator.java @@ -1,19 +1,19 @@ -package com.dfsek.terra.population; +package com.dfsek.terra.world.population; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.block.BlockType; import com.dfsek.terra.api.platform.handle.WorldHandle; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.util.world.PopulationUtil; import com.dfsek.terra.api.world.generation.TerraBlockPopulator; import com.dfsek.terra.carving.UserDefinedCarver; -import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.config.pack.WorldConfig; import com.dfsek.terra.config.templates.CarverTemplate; import com.dfsek.terra.profiler.ProfileFuture; -import com.dfsek.terra.util.PopulationUtil; import com.dfsek.terra.world.TerraWorld; import org.jetbrains.annotations.NotNull; @@ -24,7 +24,7 @@ import java.util.Random; import java.util.Set; public class CavePopulator implements TerraBlockPopulator { - private static final Map shiftStorage = new HashMap<>(); // Persist BlockData created for shifts, to avoid re-calculating each time. + private static final Map shiftStorage = new HashMap<>(); // Persist BlockData created for shifts, to avoid re-calculating each time. private final TerraPlugin main; public CavePopulator(TerraPlugin main) { @@ -40,63 +40,64 @@ public class CavePopulator implements TerraBlockPopulator { try(ProfileFuture ignored = tw.getProfiler().measure("CaveTime")) { Random random = PopulationUtil.getRandom(chunk); if(!tw.isSafe()) return; - ConfigPack config = tw.getConfig(); + WorldConfig config = tw.getConfig(); for(UserDefinedCarver c : config.getCarvers()) { CarverTemplate template = c.getConfig(); - Map shiftCandidate = new HashMap<>(); + Map shiftCandidate = new HashMap<>(); Set updateNeeded = new HashSet<>(); c.carve(chunk.getX(), chunk.getZ(), world, (v, type) -> { Block b = chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ()); - MaterialData m = handle.getType(b); + BlockData m = b.getBlockData(); + BlockType re = m.getBlockType(); switch(type) { case CENTER: - if(template.getInner().canReplace(m)) { - handle.setBlockData(b, template.getInner().get(v.getBlockY()).get(random), false); - if(template.getUpdate().contains(m)) updateNeeded.add(b); - if(template.getShift().containsKey(m)) shiftCandidate.put(b.getLocation(), m); + if(template.getInner().canReplace(re)) { + b.setBlockData(template.getInner().get(v.getBlockY()).get(random), false); + if(template.getUpdate().contains(re)) updateNeeded.add(b); + if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m); } break; case WALL: - if(template.getOuter().canReplace(m)) { - handle.setBlockData(b, template.getOuter().get(v.getBlockY()).get(random), false); - if(template.getUpdate().contains(m)) updateNeeded.add(b); - if(template.getShift().containsKey(m)) shiftCandidate.put(b.getLocation(), m); + if(template.getOuter().canReplace(re)) { + b.setBlockData(template.getOuter().get(v.getBlockY()).get(random), false); + if(template.getUpdate().contains(re)) updateNeeded.add(b); + if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m); } break; case TOP: - if(template.getTop().canReplace(m)) { - handle.setBlockData(b, template.getTop().get(v.getBlockY()).get(random), false); - if(template.getUpdate().contains(m)) updateNeeded.add(b); - if(template.getShift().containsKey(m)) shiftCandidate.put(b.getLocation(), m); + if(template.getTop().canReplace(re)) { + b.setBlockData(template.getTop().get(v.getBlockY()).get(random), false); + if(template.getUpdate().contains(re)) updateNeeded.add(b); + if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m); } break; case BOTTOM: - if(template.getBottom().canReplace(m)) { - handle.setBlockData(b, template.getBottom().get(v.getBlockY()).get(random), false); - if(template.getUpdate().contains(m)) updateNeeded.add(b); - if(template.getShift().containsKey(m)) shiftCandidate.put(b.getLocation(), m); + if(template.getBottom().canReplace(re)) { + b.setBlockData(template.getBottom().get(v.getBlockY()).get(random), false); + if(template.getUpdate().contains(re)) updateNeeded.add(b); + if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m); } break; } }); - for(Map.Entry entry : shiftCandidate.entrySet()) { + for(Map.Entry entry : shiftCandidate.entrySet()) { Location l = entry.getKey(); Location mut = l.clone(); - MaterialData orig = handle.getType(l.getBlock()); + BlockData orig = l.getBlock().getBlockData(); do mut.subtract(0, 1, 0); - while(mut.getY() > 0 && handle.getType(mut.getBlock()).equals(orig)); + while(mut.getY() > 0 && mut.getBlock().getBlockData().matches(orig)); try { - if(template.getShift().get(entry.getValue()).contains(mut.getBlock().getType())) { - handle.setBlockData(mut.getBlock(), shiftStorage.computeIfAbsent(entry.getValue(), MaterialData::createBlockData), false); + if(template.getShift().get(entry.getValue().getBlockType()).contains(mut.getBlock().getBlockData().getBlockType())) { + mut.getBlock().setBlockData(shiftStorage.computeIfAbsent(entry.getValue().getBlockType(), BlockType::getDefaultData), false); } } catch(NullPointerException ignore) { } } for(Block b : updateNeeded) { - BlockData orig = handle.getBlockData(b); - handle.setBlockData(b, AIR, false); - handle.setBlockData(b, orig, true); + BlockData orig = b.getBlockData(); + b.setBlockData(AIR, false); + b.setBlockData(orig, true); } } diff --git a/common/src/main/java/com/dfsek/terra/world/population/FloraPopulator.java b/common/src/main/java/com/dfsek/terra/world/population/FloraPopulator.java index c1318f92b..281854cce 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/FloraPopulator.java +++ b/common/src/main/java/com/dfsek/terra/world/population/FloraPopulator.java @@ -1,14 +1,14 @@ package com.dfsek.terra.world.population; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Vector2; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.util.world.PopulationUtil; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.api.world.generation.TerraBlockPopulator; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.biome.provider.BiomeProvider; import com.dfsek.terra.profiler.ProfileFuture; -import com.dfsek.terra.util.PopulationUtil; import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.population.items.flora.FloraLayer; import org.jetbrains.annotations.NotNull; diff --git a/common/src/main/java/com/dfsek/terra/world/population/OrePopulator.java b/common/src/main/java/com/dfsek/terra/world/population/OrePopulator.java index f4a60e2fc..a67944409 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/OrePopulator.java +++ b/common/src/main/java/com/dfsek/terra/world/population/OrePopulator.java @@ -1,14 +1,14 @@ package com.dfsek.terra.world.population; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.MathUtil; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; import com.dfsek.terra.api.world.generation.TerraBlockPopulator; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.config.templates.BiomeTemplate; import com.dfsek.terra.profiler.ProfileFuture; import com.dfsek.terra.world.TerraWorld; diff --git a/common/src/main/java/com/dfsek/terra/world/population/StructurePopulator.java b/common/src/main/java/com/dfsek/terra/world/population/StructurePopulator.java index a266de3dd..17bb41221 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/StructurePopulator.java +++ b/common/src/main/java/com/dfsek/terra/world/population/StructurePopulator.java @@ -1,16 +1,17 @@ package com.dfsek.terra.world.population; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.MathUtil; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.structures.structure.Rotation; import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.api.world.generation.TerraBlockPopulator; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.biome.provider.BiomeProvider; import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.config.pack.WorldConfig; import com.dfsek.terra.profiler.ProfileFuture; import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.population.items.TerraStructure; @@ -35,7 +36,7 @@ public class StructurePopulator implements TerraBlockPopulator { int cz = (chunk.getZ() << 4); if(!tw.isSafe()) return; BiomeProvider provider = tw.getBiomeProvider(); - ConfigPack config = tw.getConfig(); + WorldConfig config = tw.getConfig(); for(TerraStructure conf : config.getStructures()) { Location spawn = conf.getSpawn().getNearestSpawn(cx + 8, cz + 8, world.getSeed()).toLocation(world); diff --git a/common/src/main/java/com/dfsek/terra/world/population/TreePopulator.java b/common/src/main/java/com/dfsek/terra/world/population/TreePopulator.java index c88476971..82bf925c7 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/TreePopulator.java +++ b/common/src/main/java/com/dfsek/terra/world/population/TreePopulator.java @@ -1,14 +1,14 @@ package com.dfsek.terra.world.population; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Vector2; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.util.world.PopulationUtil; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.api.world.generation.TerraBlockPopulator; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.biome.provider.BiomeProvider; import com.dfsek.terra.profiler.ProfileFuture; -import com.dfsek.terra.util.PopulationUtil; import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.population.items.tree.TreeLayer; import net.jafama.FastMath; diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/PlaceableLayer.java b/common/src/main/java/com/dfsek/terra/world/population/items/PlaceableLayer.java index 89e39ae67..e150d92fe 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/items/PlaceableLayer.java +++ b/common/src/main/java/com/dfsek/terra/world/population/items/PlaceableLayer.java @@ -1,10 +1,10 @@ package com.dfsek.terra.world.population.items; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.math.noise.NoiseSampler; import com.dfsek.terra.api.math.vector.Vector2; import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; public abstract class PlaceableLayer { protected final double density; diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/TerraStructure.java b/common/src/main/java/com/dfsek/terra/world/population/items/TerraStructure.java index 975ea34ff..f3976fbab 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/items/TerraStructure.java +++ b/common/src/main/java/com/dfsek/terra/world/population/items/TerraStructure.java @@ -1,9 +1,9 @@ package com.dfsek.terra.world.population.items; import com.dfsek.terra.api.math.GridSpawn; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.structures.script.StructureScript; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.config.templates.StructureTemplate; public class TerraStructure { diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/flora/ConstantFlora.java b/common/src/main/java/com/dfsek/terra/world/population/items/flora/ConstantFlora.java index 45669bc36..d7bec46bf 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/items/flora/ConstantFlora.java +++ b/common/src/main/java/com/dfsek/terra/world/population/items/flora/ConstantFlora.java @@ -7,8 +7,8 @@ import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockFace; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.util.GlueList; +import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.world.flora.Flora; -import com.dfsek.terra.util.MaterialSet; import java.util.List; diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/flora/FloraLayer.java b/common/src/main/java/com/dfsek/terra/world/population/items/flora/FloraLayer.java index a5feb9c84..579b70035 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/items/flora/FloraLayer.java +++ b/common/src/main/java/com/dfsek/terra/world/population/items/flora/FloraLayer.java @@ -1,10 +1,10 @@ package com.dfsek.terra.world.population.items.flora; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.math.noise.NoiseSampler; import com.dfsek.terra.api.math.vector.Vector2; import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.world.flora.Flora; import com.dfsek.terra.world.population.items.PlaceableLayer; diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/flora/TerraFlora.java b/common/src/main/java/com/dfsek/terra/world/population/items/flora/TerraFlora.java index 4bb60eae1..0893d1c92 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/items/flora/TerraFlora.java +++ b/common/src/main/java/com/dfsek/terra/world/population/items/flora/TerraFlora.java @@ -1,6 +1,6 @@ package com.dfsek.terra.world.population.items.flora; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.Block; @@ -13,9 +13,9 @@ import com.dfsek.terra.api.platform.handle.WorldHandle; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.util.FastRandom; import com.dfsek.terra.api.util.GlueList; +import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.world.flora.Flora; import com.dfsek.terra.api.world.palette.Palette; -import com.dfsek.terra.util.MaterialSet; import net.jafama.FastMath; import java.util.ArrayList; @@ -118,7 +118,7 @@ public class TerraFlora implements Flora { ((Rotatable) data).setRotation(oneFace); } } - handle.setBlockData(location.clone().add(0, i + c, 0).getBlock(), data, physics); + location.clone().add(0, i + c, 0).getBlock().setBlockData(data, physics); } return true; } diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/ores/DeformedSphereOre.java b/common/src/main/java/com/dfsek/terra/world/population/items/ores/DeformedSphereOre.java index 4396f8028..2b4ea13ee 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/items/ores/DeformedSphereOre.java +++ b/common/src/main/java/com/dfsek/terra/world/population/items/ores/DeformedSphereOre.java @@ -1,6 +1,6 @@ package com.dfsek.terra.world.population.items.ores; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.math.noise.samplers.noise.simplex.OpenSimplex2Sampler; import com.dfsek.terra.api.math.vector.Vector3; @@ -8,7 +8,7 @@ import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.handle.WorldHandle; import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.util.MaterialSet; +import com.dfsek.terra.api.util.collections.MaterialSet; import java.util.Random; @@ -40,7 +40,7 @@ public class DeformedSphereOre extends Ore { if(oreLoc.distance(origin) < (rad + 0.5) * ((ore.getNoise(x, y, z) + 1) * deform)) { Block b = c.getBlock(oreLoc.getBlockX(), oreLoc.getBlockY(), oreLoc.getBlockZ()); if(getReplaceable().contains(b.getType()) && b.getLocation().getY() >= 0) - handle.setBlockData(b, getMaterial(), isApplyGravity()); + b.setBlockData(getMaterial(), isApplyGravity()); } } } diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/ores/Ore.java b/common/src/main/java/com/dfsek/terra/world/population/items/ores/Ore.java index 231b625a9..541a7dacf 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/items/ores/Ore.java +++ b/common/src/main/java/com/dfsek/terra/world/population/items/ores/Ore.java @@ -1,10 +1,10 @@ package com.dfsek.terra.world.population.items.ores; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.util.MaterialSet; +import com.dfsek.terra.api.util.collections.MaterialSet; import java.util.Random; diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/ores/VanillaOre.java b/common/src/main/java/com/dfsek/terra/world/population/items/ores/VanillaOre.java index 5c19f5246..549e1e378 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/items/ores/VanillaOre.java +++ b/common/src/main/java/com/dfsek/terra/world/population/items/ores/VanillaOre.java @@ -1,13 +1,12 @@ package com.dfsek.terra.world.population.items.ores; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.handle.WorldHandle; import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.util.MaterialSet; +import com.dfsek.terra.api.util.collections.MaterialSet; import net.jafama.FastMath; import java.util.Random; @@ -23,7 +22,6 @@ public class VanillaOre extends Ore { @Override public void generate(Vector3 location, Chunk chunk, Random random) { - WorldHandle handle = main.getWorldHandle(); double size = sizeRange.get(random); int centerX = location.getBlockX(); @@ -31,29 +29,31 @@ public class VanillaOre extends Ore { int centerY = location.getBlockY(); - float f = random.nextFloat() * (float) Math.PI; + double f = random.nextFloat() * Math.PI; - double d1 = centerX + 8 + FastMath.sin(f) * size / 8.0F; - double d2 = centerX + 8 - FastMath.sin(f) * size / 8.0F; - double d3 = centerZ + 8 + FastMath.cos(f) * size / 8.0F; - double d4 = centerZ + 8 - FastMath.cos(f) * size / 8.0F; + double fS = FastMath.sin(f) * size / 8.0F; + double fC = FastMath.cos(f) * size / 8.0F; + + double d1 = centerX + 8 + fS; + double d2 = centerX + 8 - fS; + double d3 = centerZ + 8 + fC; + double d4 = centerZ + 8 - fC; double d5 = centerY + random.nextInt(3) - 2D; double d6 = centerY + random.nextInt(3) - 2D; for(int i = 0; i < size; i++) { - float iFactor = (float) i / (float) size; + double iFactor = i / size; double d10 = random.nextDouble() * size / 16.0D; double d11 = (FastMath.sin(Math.PI * iFactor) + 1.0) * d10 + 1.0; - double d12 = (FastMath.sin(Math.PI * iFactor) + 1.0) * d10 + 1.0; int xStart = FastMath.roundToInt(FastMath.floor(d1 + (d2 - d1) * iFactor - d11 / 2.0D)); - int yStart = FastMath.roundToInt(FastMath.floor(d5 + (d6 - d5) * iFactor - d12 / 2.0D)); + int yStart = FastMath.roundToInt(FastMath.floor(d5 + (d6 - d5) * iFactor - d11 / 2.0D)); int zStart = FastMath.roundToInt(FastMath.floor(d3 + (d4 - d3) * iFactor - d11 / 2.0D)); int xEnd = FastMath.roundToInt(FastMath.floor(d1 + (d2 - d1) * iFactor + d11 / 2.0D)); - int yEnd = FastMath.roundToInt(FastMath.floor(d5 + (d6 - d5) * iFactor + d12 / 2.0D)); + int yEnd = FastMath.roundToInt(FastMath.floor(d5 + (d6 - d5) * iFactor + d11 / 2.0D)); int zEnd = FastMath.roundToInt(FastMath.floor(d3 + (d4 - d3) * iFactor + d11 / 2.0D)); for(int x = xStart; x <= xEnd; x++) { @@ -61,14 +61,14 @@ public class VanillaOre extends Ore { if(d13 * d13 < 1.0D) { for(int y = yStart; y <= yEnd; y++) { - double d14 = (y + 0.5D - (d5 + (d6 - d5) * iFactor)) / (d12 / 2.0D); + double d14 = (y + 0.5D - (d5 + (d6 - d5) * iFactor)) / (d11 / 2.0D); if(d13 * d13 + d14 * d14 < 1.0D) { for(int z = zStart; z <= zEnd; z++) { double d15 = (z + 0.5D - (d3 + (d4 - d3) * iFactor)) / (d11 / 2.0D); if(x > 15 || z > 15 || y > 255 || x < 0 || z < 0 || y < 0) continue; Block block = chunk.getBlock(x, y, z); if((d13 * d13 + d14 * d14 + d15 * d15 < 1.0D) && getReplaceable().contains(block.getType())) { - handle.setBlockData(block, getMaterial(), isApplyGravity()); + block.setBlockData(getMaterial(), isApplyGravity()); } } } diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/tree/TerraTree.java b/common/src/main/java/com/dfsek/terra/world/population/items/tree/TerraTree.java index 7b24a9eb4..07c4ae283 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/items/tree/TerraTree.java +++ b/common/src/main/java/com/dfsek/terra/world/population/items/tree/TerraTree.java @@ -1,11 +1,11 @@ package com.dfsek.terra.world.population.items.tree; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.structures.script.StructureScript; import com.dfsek.terra.api.structures.structure.Rotation; +import com.dfsek.terra.api.util.collections.MaterialSet; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.world.tree.Tree; -import com.dfsek.terra.util.MaterialSet; import java.util.Random; diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/tree/TreeLayer.java b/common/src/main/java/com/dfsek/terra/world/population/items/tree/TreeLayer.java index 461b633be..4f90b1be7 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/items/tree/TreeLayer.java +++ b/common/src/main/java/com/dfsek/terra/world/population/items/tree/TreeLayer.java @@ -1,14 +1,14 @@ package com.dfsek.terra.world.population.items.tree; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.math.noise.NoiseSampler; import com.dfsek.terra.api.math.vector.Vector2; import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.BlockFace; import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; +import com.dfsek.terra.api.util.world.PopulationUtil; import com.dfsek.terra.api.world.tree.Tree; -import com.dfsek.terra.util.PopulationUtil; import com.dfsek.terra.world.population.items.PlaceableLayer; public class TreeLayer extends PlaceableLayer { diff --git a/platforms/bukkit/src/main/resources/config.yml b/common/src/main/resources/config.yml similarity index 100% rename from platforms/bukkit/src/main/resources/config.yml rename to common/src/main/resources/config.yml diff --git a/platforms/bukkit/src/main/resources/lang/afr_sa.yml b/common/src/main/resources/lang/afr_sa.yml similarity index 100% rename from platforms/bukkit/src/main/resources/lang/afr_sa.yml rename to common/src/main/resources/lang/afr_sa.yml diff --git a/src/main/resources/lang/da.yml b/common/src/main/resources/lang/da.yml similarity index 100% rename from src/main/resources/lang/da.yml rename to common/src/main/resources/lang/da.yml diff --git a/platforms/bukkit/src/main/resources/lang/de_de.yml b/common/src/main/resources/lang/de_de.yml similarity index 100% rename from platforms/bukkit/src/main/resources/lang/de_de.yml rename to common/src/main/resources/lang/de_de.yml diff --git a/platforms/bukkit/src/main/resources/lang/en_us.yml b/common/src/main/resources/lang/en_us.yml similarity index 99% rename from platforms/bukkit/src/main/resources/lang/en_us.yml rename to common/src/main/resources/lang/en_us.yml index 048e36e0f..cde2101d9 100644 --- a/platforms/bukkit/src/main/resources/lang/en_us.yml +++ b/common/src/main/resources/lang/en_us.yml @@ -112,7 +112,7 @@ warning: error: severe-config: "A severe configuration error has prevented Terra from properly generating terrain at coordinates: %1$s, %2$s. Please check your configuration for errors. Any config errors will have been reported above." debug: - data-save: "Saved population data for world \"%s\"" + data-save : "Saved population data." use-paper: - "You appear to be using Spigot/CraftBukkit." - "While Terra &odoes&r work on Spigot, some functionality will be lost. (Terra is untested on CraftBukkit; no support will be given for CraftBukkit)." diff --git a/platforms/bukkit/src/main/resources/lang/es.yml b/common/src/main/resources/lang/es.yml similarity index 100% rename from platforms/bukkit/src/main/resources/lang/es.yml rename to common/src/main/resources/lang/es.yml diff --git a/platforms/bukkit/src/main/resources/lang/it_it.yml b/common/src/main/resources/lang/it_it.yml similarity index 100% rename from platforms/bukkit/src/main/resources/lang/it_it.yml rename to common/src/main/resources/lang/it_it.yml diff --git a/platforms/bukkit/src/main/resources/lang/ja_jp.yml b/common/src/main/resources/lang/ja_jp.yml similarity index 100% rename from platforms/bukkit/src/main/resources/lang/ja_jp.yml rename to common/src/main/resources/lang/ja_jp.yml diff --git a/platforms/bukkit/src/main/resources/lang/nl_NL.yml b/common/src/main/resources/lang/nl_NL.yml similarity index 100% rename from platforms/bukkit/src/main/resources/lang/nl_NL.yml rename to common/src/main/resources/lang/nl_NL.yml diff --git a/platforms/bukkit/src/main/resources/lang/pl.yml b/common/src/main/resources/lang/pl.yml similarity index 100% rename from platforms/bukkit/src/main/resources/lang/pl.yml rename to common/src/main/resources/lang/pl.yml diff --git a/common/src/main/resources/lang/ru.yml b/common/src/main/resources/lang/ru.yml new file mode 100644 index 000000000..f0c8db834 --- /dev/null +++ b/common/src/main/resources/lang/ru.yml @@ -0,0 +1,122 @@ +enable: + - "Если вам нравится Terra, пожалуйста, поддержите проект на Patreon!" + - "Вы получите доступ к экспериментальным функциям ещё до их релиза!" + - "Поддержите проект здесь: https://www.patreon.com/dfsek" +disable: + - "Благодарим за использование Terra!" +command: + debug-only: "Эта команда может быть введена только в режиме отладки!" + player-only: "Эту команду могут вводить только игроки!" + invalid: "Неверная команда. (Ожидался аргумент %1$s, найден %2$s)." + players-only: "Команда только для игроков." + world: "Эта команда может быть введена только в мире с Terra!" + reload: "Конфигурации Terra перезагружена." + reload-error: "Во время перезагрузки конфигураций Terra произошла ошибка. Просмотрите логи для более детальной информации." + version: "This server is running Terra version \"%1$s\", on platform \"%2$s\"" + main-menu: + - "--------------------Terra--------------------" + - "reload - Перезагрузить конфигурации" + - "biome - Узнать текущий биом" + - "ore - Сгенерировать жилу руд на месте вашего взора (Для отладки)" + - "save-data - Сохранить данные популяции" + - "structure - Загрузить и экспортировать структуры" + - "profile - Команды профайлера" + - "image - Команды образа/интерфейса" + biome: + biome-found: "Биом найден на (%1$s, %2$s)" + unable-to-locate: "Не получилось найти биом." + invalid-radius: "Неверный радиус: \"%s\"" + invalid: "Неверный ID биома: \"%s\"" + in: "Вы находитесь в \"%s\"" + packs: + main: "Установленные наборы конфигураций:" + pack: " - %1$s вер.%3$s от %2$s" + none: "Наборы конфигураций не установлены." + ore: + main-menu: + - "---------------Terra/ore---------------" + - "Генерирует жилу руд на месте вашего взора." + out-of-range: "Блок слишком далеко" + invalid-ore: "Не получилось найти руду \"%s\"" + geometry: + main-menu: + - "---------------Terra/geometry----------------" + - "Различные команды отладки воксельной геометрии" + - "sphere - Сгенерировать сферу" + - "deformsphere - Сгенерировать деформированную сферу" + - "tube - Сгенерировать трубу" + deform: + invalid-radius: "Неверный радиус: \"%s\"" + invalid-deform: "Неверная деформация: \"%s\"" + invalid-frequency: "Неверная частота: \"%s\"" + sphere: + invalid-radius: "Неверный радиус: \"%s\"" + tube: + invalid-radius: "Неверный радиус: \"%s\"" + image: + main-menu: + - "---------------Terra/image---------------" + - "render - Прорендерить образ с указанными шириной и высотой, который позже может быть импортирован как мир." + - "gui - Открыть интерфейс отладки (Должно быть включено в конфигурации)" + gui: + main-menu: + - "-------------Terra/image/gui-------------" + - "raw - Открыть интерфейс с сырыми данными биомов" + - "step - Перерендерить данные для более ясного видения границ" + debug: "Для использования этого интерфейса должен быть включен режим отладки! Режим отладки НЕБЕЗОПАСЕН ДЛЯ СЕРВЕРОВ!" + render: + save: "Образ сохранен как \"%s\"" + error: "Во время генерации образа произошла ошибка!" + profile: + main-menu: + - "---------------Terra/profile---------------" + - "start - Начать анализ профайлером" + - "stop - Остановить анализ профайлером" + - "query - Получить данные профайлера" + - "reset - Обнулить данные профайлера" + reset: "Данные профайлера были обнулены." + start: "Анализ профайлером начат." + stop: "Анализ профайлером остановлен." + structure: + main-menu: + - "---------------Terra/structure---------------" + - "export - Экспортировать выделение WorldEdit'а как структуру Terra" + - "load - Загрузить структуру Terra" + invalid-radius: "Неверный радиус: \"%s\"" + invalid-rotation: "Неверный поворот: \"%s\"" + invalid: "Неверный ID структуры: \"%s\"" + export: "Структура сохранена как \"%s\"" +world-config: + load: "Значения конфигурации мира \"%s\" загружаются..." + not-found: "Конфигурация мира \"%s\" не найдена. Копирование обычной." + using-image: "Загрузка мира с образа." + error: "Не получилось загрузить конфигурацию мира %s" + done: "Загрузка мира \"%1$s\" завершена. Затрачено времени: %2$sмс" +config-pack: + loaded: "Набор конфигураций %1$s вер.%4$s от %3$s загружен за %2$sмс." +config: + loaded: "Загружен %1$s с файла %2$s" + loaded-all: "Загружено %1$s %2$s за %3$sмс." + error: + invalid-failover: "Неверный тип аварийного переключения: \"%s\"" + duplicate: "Дублирующийся ID найден в файле: %s" + file: + - "Ошибка конфигурации объекта Terra. Файл: %1$s" + - "%2$s" + - "Прежде чем продолжить, исправьте это!" + generic: + - "Во время загрузки конфигураций произошла ошибка." + - "Пожалуйста, сообщите об этом разработчикам Terra." +warning: + no-population: "Не было загружено популяторов чанков. Если вы впервые запускаете сервер с Terra или создаете новый мир, то всё в порядке." +error: + severe-config: "Несколько ошибок конфигруации не позволили Terra сгенерировать область нормально по этим координатам: %1$s, %2$s. Пожалуйста, проверьте свою конфигурацию на наличие ошибок. Все ошибки были показаны выше." +debug: + data-save: "Данные популяции мира \"%s\" сохранены" +use-paper: + - "Похоже, что вы используете Spigot/CraftBukkit." + - "Пускай Terra и &oработает&r со Spigot, часть функционала плагина не работает. (Terra не тестировался с CraftBukkit; не ожидайте поддержки для CraftBukkit)." + - "Чтобы получить весь функционал Terra, пожалуйста, используйте Paper." + - "Кроме того, Paper намного производительнее, чем Spigot, а все плагины Spigot должны работать и на Paper!" + - "Если вы хотите получить лучший опыт использования Terra и иных плагинов, пожалуйста, предпочтите Paper." + - "Больше о Paper можно узнать на сайте: https://papermc.io/" diff --git a/platforms/bukkit/src/main/resources/lang/zh_cn.yml b/common/src/main/resources/lang/zh_cn.yml similarity index 100% rename from platforms/bukkit/src/main/resources/lang/zh_cn.yml rename to common/src/main/resources/lang/zh_cn.yml diff --git a/common/src/test/java/biome/DistributionTest.java b/common/src/test/java/biome/DistributionTest.java index 6ffe4da82..226da5898 100644 --- a/common/src/test/java/biome/DistributionTest.java +++ b/common/src/test/java/biome/DistributionTest.java @@ -9,32 +9,36 @@ import com.dfsek.tectonic.config.ValidatedConfigTemplate; import com.dfsek.tectonic.exception.ConfigException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeRegistry; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.api.core.event.EventManager; -import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.addons.TerraAddon; +import com.dfsek.terra.api.event.EventManager; import com.dfsek.terra.api.platform.handle.ItemHandle; import com.dfsek.terra.api.platform.handle.WorldHandle; import com.dfsek.terra.api.platform.world.Biome; import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.registry.LockedRegistry; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; +import com.dfsek.terra.api.util.logging.DebugLogger; +import com.dfsek.terra.api.util.logging.JavaLogger; import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.world.biome.Generator; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.config.GenericLoaders; import com.dfsek.terra.config.PluginConfig; +import com.dfsek.terra.config.builder.BiomeBuilder; import com.dfsek.terra.config.fileloaders.FolderLoader; import com.dfsek.terra.config.lang.Language; import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader; import com.dfsek.terra.config.loaders.config.BufferedImageLoader; import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader; -import com.dfsek.terra.config.loaders.config.biome.templates.source.BiomePipelineTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.source.ImageProviderTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.source.SingleBiomeProviderTemplate; +import com.dfsek.terra.config.loaders.config.biome.templates.provider.BiomePipelineTemplate; +import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProviderTemplate; +import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiomeProviderTemplate; import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader; import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.templates.AbstractableTemplate; -import com.dfsek.terra.debug.DebugLogger; -import com.dfsek.terra.registry.ConfigRegistry; import com.dfsek.terra.registry.config.BiomeRegistry; import com.dfsek.terra.registry.config.NoiseRegistry; import com.dfsek.terra.world.TerraWorld; @@ -62,19 +66,14 @@ public class DistributionTest { return null; } - @Override - public boolean isEnabled() { - return false; - } - @Override public TerraWorld getWorld(World world) { return null; } @Override - public Logger getLogger() { - return Logger.getLogger("Terra"); + public com.dfsek.terra.api.util.logging.Logger logger() { + return new JavaLogger(Logger.getLogger("Terra")); } @Override @@ -98,13 +97,18 @@ public class DistributionTest { } @Override - public ConfigRegistry getRegistry() { + public CheckedRegistry getConfigRegistry() { return null; } @Override - public void reload() { + public LockedRegistry getAddons() { + return null; + } + @Override + public boolean reload() { + return true; } @Override @@ -124,7 +128,7 @@ public class DistributionTest { @Override public DebugLogger getDebugLogger() { - return new DebugLogger(Logger.getLogger("Terra")); + return new DebugLogger(new JavaLogger(Logger.getLogger("Terra"))); } @Override @@ -141,11 +145,11 @@ public class DistributionTest { private static BiomeProvider getProvider(long seed) throws ConfigException, IOException { System.out.println(seed); - File pack = new File("/home/dfsek/Documents/Terra/platforms/bukkit/target/server/plugins/Terra/packs/betterend/"); + File pack = new File("/home/dfsek/Documents/Terra/platforms/bukkit/target/server/plugins/Terra/packs/default/"); FolderLoader folderLoader = new FolderLoader(pack.toPath()); AbstractConfigLoader loader = new AbstractConfigLoader(); - new GenericLoaders(null).register(loader); + new GenericLoaders(MAIN).register(loader); BiomeRegistry biomeRegistry = new BiomeRegistry(); folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.load(inputStreams, TestBiome::new), MAIN)); @@ -154,12 +158,12 @@ public class DistributionTest { ConfigLoader pipeLoader = new ConfigLoader() .registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader()) .registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader()) - .registerLoader(TerraBiome.class, biomeRegistry) + .registerLoader(BiomeBuilder.class, biomeRegistry) .registerLoader(BufferedImage.class, new BufferedImageLoader(folderLoader)) - .registerLoader(SingleBiomeProviderTemplate.class, () -> new SingleBiomeProviderTemplate(biomeRegistry)) - .registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(biomeRegistry, MAIN)) + .registerLoader(SingleBiomeProviderTemplate.class, SingleBiomeProviderTemplate::new) + .registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(MAIN)) .registerLoader(ImageProviderTemplate.class, () -> new ImageProviderTemplate(biomeRegistry)); - new GenericLoaders(null).register(pipeLoader); + new GenericLoaders(MAIN).register(pipeLoader); pipeLoader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(new NoiseRegistry())); @@ -282,7 +286,7 @@ public class DistributionTest { } } - private static final class TestBiome extends AbstractableTemplate implements TerraBiome, ValidatedConfigTemplate { + private static final class TestBiome extends AbstractableTemplate implements TerraBiome, ValidatedConfigTemplate, BiomeBuilder { @Value("color") @Default @@ -333,5 +337,10 @@ public class DistributionTest { public String toString() { return id; } + + @Override + public TestBiome apply(Long aLong) { + return this; + } } } diff --git a/common/src/test/java/biome/ImageTest.java b/common/src/test/java/biome/ImageTest.java index 916a68c00..ddc96dafc 100644 --- a/common/src/test/java/biome/ImageTest.java +++ b/common/src/test/java/biome/ImageTest.java @@ -7,17 +7,17 @@ import com.dfsek.tectonic.annotations.Value; import com.dfsek.tectonic.config.ConfigTemplate; import com.dfsek.tectonic.config.ValidatedConfigTemplate; import com.dfsek.tectonic.exception.ConfigException; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.platform.world.Biome; import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.world.biome.Generator; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.provider.BiomeProvider; -import com.dfsek.terra.biome.provider.ImageBiomeProvider; +import com.dfsek.terra.api.world.biome.TerraBiome; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.biome.provider.ImageBiomeProvider; import com.dfsek.terra.config.fileloaders.FolderLoader; import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.templates.AbstractableTemplate; -import com.dfsek.terra.registry.TerraRegistry; +import com.dfsek.terra.registry.OpenRegistry; import org.junit.jupiter.api.Test; import javax.imageio.ImageIO; @@ -44,11 +44,11 @@ public class ImageTest { AbstractConfigLoader loader = new AbstractConfigLoader(); - TerraRegistry biomeRegistry = new TerraRegistry() { + OpenRegistry biomeRegistry = new OpenRegistry() { }; folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.load(inputStreams, TestBiome::new), null)); - return new ImageBiomeProvider(biomeRegistry, ImageIO.read(ImageTest.class.getResourceAsStream("/map.jpg")), 1, ImageBiomeProvider.Align.CENTER); + return new ImageBiomeProvider(biomeRegistry.entries(), ImageIO.read(ImageTest.class.getResourceAsStream("/map.jpg")), 1, ImageBiomeProvider.Align.CENTER); } @Test diff --git a/common/src/test/java/command/CommandTest.java b/common/src/test/java/command/CommandTest.java new file mode 100644 index 000000000..f3cd29337 --- /dev/null +++ b/common/src/test/java/command/CommandTest.java @@ -0,0 +1,236 @@ +package command; + +import com.dfsek.terra.api.command.CommandManager; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.TerraCommandManager; +import com.dfsek.terra.api.command.annotation.Argument; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.Subcommand; +import com.dfsek.terra.api.command.annotation.Switch; +import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; +import com.dfsek.terra.api.command.annotation.inject.SwitchTarget; +import com.dfsek.terra.api.command.arg.DoubleArgumentParser; +import com.dfsek.terra.api.command.arg.IntegerArgumentParser; +import com.dfsek.terra.api.command.exception.CommandException; +import com.dfsek.terra.api.command.exception.InvalidArgumentsException; +import com.dfsek.terra.api.command.exception.MalformedCommandException; +import com.dfsek.terra.api.platform.CommandSender; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.fail; + +public class CommandTest { + @Test + public void subcommand() throws CommandException { + CommandManager manager = new TerraCommandManager(null); + manager.register("test", DemoParentCommand.class); + + manager.execute("test", null, Arrays.asList("subcommand1", "first", "2")); + manager.execute("test", null, Arrays.asList("subcommand2", "first", "2")); + manager.execute("test", null, Arrays.asList("s1", "first", "2", "3.4")); + manager.execute("test", null, Arrays.asList("s2", "first", "2")); + manager.execute("test", null, Arrays.asList("sub1", "first", "2", "3.4")); + manager.execute("test", null, Arrays.asList("sub2", "first", "2")); + manager.execute("test", null, Arrays.asList("first", "2")); // Parent command args + + System.out.println("ARGS: " + manager.getMaxArgumentDepth()); + } + + @Test + public void args() throws CommandException { + CommandManager manager = new TerraCommandManager(null); + manager.register("test", DemoCommand.class); + + manager.execute("test", null, Arrays.asList("first", "2")); + manager.execute("test", null, Arrays.asList("first", "2", "3.4")); + } + + @Test + public void argsBeforeFlags() throws CommandException { + CommandManager manager = new TerraCommandManager(null); + manager.register("test", DemoCommand.class); + + try { + manager.execute("test", null, Arrays.asList("first", "-flag", "2")); + fail(); + } catch(InvalidArgumentsException ignore) { + } + } + + @Test + public void requiredArgsFirst() throws CommandException { + CommandManager manager = new TerraCommandManager(null); + manager.register("test", DemoInvalidCommand.class); + + try { + manager.execute("test", null, Arrays.asList("first", "2")); + fail(); + } catch(MalformedCommandException ignore) { + } + } + + @Test + public void switches() throws CommandException { + CommandManager manager = new TerraCommandManager(null); + manager.register("test", DemoSwitchCommand.class); + + manager.execute("test", null, Arrays.asList("first", "2")); + manager.execute("test", null, Arrays.asList("first", "2", "3.4")); + + manager.execute("test", null, Arrays.asList("first", "2", "-a")); + manager.execute("test", null, Arrays.asList("first", "2", "3.4", "-b")); + + manager.execute("test", null, Arrays.asList("first", "2", "-aSwitch")); + manager.execute("test", null, Arrays.asList("first", "2", "3.4", "-bSwitch")); + + manager.execute("test", null, Arrays.asList("first", "2", "-aSwitch", "-b")); + manager.execute("test", null, Arrays.asList("first", "2", "3.4", "-bSwitch", "-a")); + } + + @Command( + arguments = { + @Argument(value = "arg0"), + @Argument(value = "arg1", argumentParser = IntegerArgumentParser.class), + @Argument(value = "arg2", required = false, argumentParser = DoubleArgumentParser.class) + } + ) + public static final class DemoCommand implements CommandTemplate { + + @ArgumentTarget("arg0") + private String arg0; + + @ArgumentTarget("arg1") + private Integer arg1; + + @ArgumentTarget("arg2") + private Double arg2; + + + @Override + public void execute(CommandSender sender) { + System.out.println(arg0); + System.out.println(arg1); + System.out.println(arg2); + } + } + + @Command( + arguments = { + @Argument(value = "arg0"), + @Argument(value = "arg1"), + @Argument(value = "arg2", required = false) + }, + switches = { + @Switch(value = "a", aliases = {"aSwitch"}), + @Switch(value = "b", aliases = {"bSwitch"}) + } + ) + public static final class DemoSwitchCommand implements CommandTemplate { + @ArgumentTarget("arg0") + private String arg0; + + @ArgumentTarget("arg1") + private String arg1; + + @ArgumentTarget("arg2") + private String arg2; + + @SwitchTarget("a") + private boolean a; + + @SwitchTarget("b") + private boolean b; + + + @Override + public void execute(CommandSender sender) { + System.out.println(arg0); + System.out.println(arg1); + System.out.println(arg2); + + System.out.println("A: " + a); + System.out.println("B: " + b); + } + } + + @Command( + arguments = { + @Argument(value = "arg0"), + @Argument(value = "arg2", required = false), // optional arguments must be last. this command is invalid. + @Argument(value = "arg1") + } + ) + public static final class DemoInvalidCommand implements CommandTemplate { + + @Override + public void execute(CommandSender sender) { + throw new Error("this should never be reached"); + } + } + + @Command( + arguments = { + @Argument(value = "arg0"), + @Argument(value = "arg1"), + @Argument(value = "arg2", required = false), + }, + subcommands = { + @Subcommand( + value = "subcommand1", + aliases = {"s1", "sub1"}, + clazz = DemoChildCommand.class + ), + @Subcommand( + value = "subcommand2", + aliases = {"s2", "sub2"}, + clazz = DemoChildCommand.class // Duplicate command intentional. + ) + } + ) + public static final class DemoParentCommand implements CommandTemplate { + @ArgumentTarget("arg0") + private String arg0; + + @ArgumentTarget("arg1") + private String arg1; + + @ArgumentTarget("arg2") + private String arg2; + + + @Override + public void execute(CommandSender sender) { + System.out.println(arg0); + System.out.println(arg1); + System.out.println(arg2); + } + } + + @Command( + arguments = { + @Argument(value = "arg0"), + @Argument(value = "arg1"), + @Argument(value = "arg2", required = false), + } + ) + public static final class DemoChildCommand implements CommandTemplate { + @ArgumentTarget("arg0") + private String arg0; + + @ArgumentTarget("arg1") + private String arg1; + + @ArgumentTarget("arg2") + private String arg2; + + + @Override + public void execute(CommandSender sender) { + System.out.println(arg0); + System.out.println(arg1); + System.out.println(arg2); + } + } +} diff --git a/common/src/test/java/event/EventTest.java b/common/src/test/java/event/EventTest.java deleted file mode 100644 index 00f16f1ad..000000000 --- a/common/src/test/java/event/EventTest.java +++ /dev/null @@ -1,150 +0,0 @@ -package event; - -import com.dfsek.tectonic.loading.TypeRegistry; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.api.core.event.annotations.Priority; -import com.dfsek.terra.api.core.event.events.Event; -import com.dfsek.terra.api.core.event.EventListener; -import com.dfsek.terra.api.core.event.EventManager; -import com.dfsek.terra.api.core.event.TerraEventManager; -import com.dfsek.terra.api.platform.handle.ItemHandle; -import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.config.PluginConfig; -import com.dfsek.terra.config.lang.Language; -import com.dfsek.terra.debug.DebugLogger; -import com.dfsek.terra.registry.ConfigRegistry; -import com.dfsek.terra.world.TerraWorld; -import org.junit.jupiter.api.Test; - -import java.io.File; -import java.util.logging.Logger; - -public class EventTest { - public TerraPlugin main = new TerraPlugin() { - private final Logger logger = Logger.getLogger("Terra"); - private final EventManager eventManager = new TerraEventManager(this); - - @Override - public WorldHandle getWorldHandle() { - return null; - } - - @Override - public boolean isEnabled() { - return false; - } - - @Override - public TerraWorld getWorld(World world) { - return null; - } - - @Override - public Logger getLogger() { - return logger; - } - - @Override - public PluginConfig getTerraConfig() { - return null; - } - - @Override - public File getDataFolder() { - return null; - } - - @Override - public boolean isDebug() { - return false; - } - - @Override - public Language getLanguage() { - return null; - } - - @Override - public ConfigRegistry getRegistry() { - return null; - } - - @Override - public void reload() { - - } - - @Override - public ItemHandle getItemHandle() { - return null; - } - - @Override - public void saveDefaultConfig() { - - } - - @Override - public String platformName() { - return null; - } - - @Override - public DebugLogger getDebugLogger() { - return null; - } - - @Override - public void register(TypeRegistry registry) { - - } - - @Override - public EventManager getEventManager() { - return eventManager; - } - }; - - @Test - public void eventTest() { - EventManager eventManager = main.getEventManager(); - eventManager.registerListener(new TestListener()); - eventManager.registerListener(new TestListener2()); - - TestEvent event = new TestEvent(4); - eventManager.callEvent(event); - - eventManager.registerListener(new TestListenerException()); - - TestEvent event2 = new TestEvent(5); - eventManager.callEvent(event2); - } - - static class TestListener implements EventListener { - public void doThing(TestEvent event) { - System.out.println("Event value: " + event.value); - } - } - - static class TestListener2 implements EventListener { - @Priority(Priority.LOWEST) - public void doThing(TestEvent event) { - System.out.println("Event value 2: " + event.value); - } - } - - static class TestListenerException implements EventListener { - public void doThing(TestEvent event) { - throw new RuntimeException("bazinga: " + event.value); - } - } - - static class TestEvent implements Event { - private final int value; - - TestEvent(int value) { - this.value = value; - } - } -} diff --git a/common/src/test/java/noise/ColorConfigTemplate.java b/common/src/test/java/noise/ColorConfigTemplate.java index 0a8c88556..ddc3ba9f0 100644 --- a/common/src/test/java/noise/ColorConfigTemplate.java +++ b/common/src/test/java/noise/ColorConfigTemplate.java @@ -3,7 +3,7 @@ package noise; import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; import com.dfsek.tectonic.config.ConfigTemplate; -import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; public class ColorConfigTemplate implements ConfigTemplate { @Value("colors") diff --git a/common/src/test/java/noise/NoiseTool.java b/common/src/test/java/noise/NoiseTool.java index ef518aa1b..a335a88de 100644 --- a/common/src/test/java/noise/NoiseTool.java +++ b/common/src/test/java/noise/NoiseTool.java @@ -2,8 +2,8 @@ package noise; import com.dfsek.tectonic.exception.ConfigException; import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.noise.NoiseSampler; +import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.config.GenericLoaders; import com.dfsek.terra.config.fileloaders.FolderLoader; diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6ca79a242..aec6aa17c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -org.gradle.jvmargs=-Xmx2048m \ No newline at end of file +org.gradle.jvmargs=-Xmx4096m \ No newline at end of file diff --git a/platforms/bukkit/build.gradle.kts b/platforms/bukkit/build.gradle.kts index ebf64f845..dbf066f36 100644 --- a/platforms/bukkit/build.gradle.kts +++ b/platforms/bukkit/build.gradle.kts @@ -31,15 +31,8 @@ dependencies { "shadedImplementation"("org.bstats:bstats-bukkit:1.7") "compileOnly"("com.sk89q.worldedit:worldedit-bukkit:7.2.0-SNAPSHOT") -} -tasks.withType { - include("**/*.yml") - filter( - "tokens" to mapOf( - "VERSION" to project.version.toString() - ) - ) + "shadedImplementation"("com.google.guava:guava:30.0-jre") } val testDir = "target/server/" diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java index 8d70cfa10..ff3bd80ec 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java @@ -2,6 +2,7 @@ package com.dfsek.terra.bukkit; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.entity.Entity; +import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.bukkit.world.BukkitAdapter; public class BukkitEntity implements Entity { @@ -21,6 +22,16 @@ public class BukkitEntity implements Entity { return BukkitAdapter.adapt(entity.getLocation()); } + @Override + public void setLocation(Location location) { + entity.teleport(BukkitAdapter.adapt(location)); + } + + @Override + public World getWorld() { + return BukkitAdapter.adapt(entity.getWorld()); + } + @Override public void sendMessage(String message) { entity.sendMessage(message); diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java index 0251d2ada..822fa0d7c 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java @@ -1,7 +1,8 @@ package com.dfsek.terra.bukkit; import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.Player; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.bukkit.world.BukkitAdapter; public class BukkitPlayer implements Player { @@ -22,6 +23,16 @@ public class BukkitPlayer implements Player { return new Location(BukkitAdapter.adapt(bukkit.getWorld()), bukkit.getX(), bukkit.getY(), bukkit.getZ()); } + @Override + public void setLocation(Location location) { + delegate.teleport(BukkitAdapter.adapt(location)); + } + + @Override + public World getWorld() { + return BukkitAdapter.adapt(delegate.getWorld()); + } + @Override public void sendMessage(String message) { delegate.sendMessage(message); diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java index 5e2a75f4a..e1254e51e 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java @@ -1,17 +1,30 @@ package com.dfsek.terra.bukkit; import com.dfsek.tectonic.loading.TypeRegistry; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.api.core.event.EventManager; -import com.dfsek.terra.api.core.event.TerraEventManager; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.addons.TerraAddon; +import com.dfsek.terra.api.addons.annotations.Addon; +import com.dfsek.terra.api.addons.annotations.Author; +import com.dfsek.terra.api.addons.annotations.Version; +import com.dfsek.terra.api.command.CommandManager; +import com.dfsek.terra.api.command.TerraCommandManager; +import com.dfsek.terra.api.command.exception.MalformedCommandException; +import com.dfsek.terra.api.event.EventManager; +import com.dfsek.terra.api.event.TerraEventManager; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; import com.dfsek.terra.api.platform.handle.ItemHandle; import com.dfsek.terra.api.platform.handle.WorldHandle; import com.dfsek.terra.api.platform.world.Biome; import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.bukkit.command.command.TerraCommand; -import com.dfsek.terra.bukkit.command.command.structure.LocateCommand; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.registry.LockedRegistry; +import com.dfsek.terra.api.util.logging.DebugLogger; +import com.dfsek.terra.api.util.logging.JavaLogger; +import com.dfsek.terra.api.util.logging.Logger; +import com.dfsek.terra.api.world.generation.TerraChunkGenerator; +import com.dfsek.terra.bukkit.command.BukkitCommandAdapter; +import com.dfsek.terra.bukkit.command.FixChunkCommand; +import com.dfsek.terra.bukkit.command.SaveDataCommand; import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; import com.dfsek.terra.bukkit.handles.BukkitItemHandle; import com.dfsek.terra.bukkit.handles.BukkitWorldHandle; @@ -21,15 +34,16 @@ import com.dfsek.terra.bukkit.listeners.SpigotListener; import com.dfsek.terra.bukkit.listeners.TerraListener; import com.dfsek.terra.bukkit.util.PaperUtil; import com.dfsek.terra.bukkit.world.BukkitBiome; +import com.dfsek.terra.commands.CommandUtil; import com.dfsek.terra.config.GenericLoaders; import com.dfsek.terra.config.PluginConfig; import com.dfsek.terra.config.lang.LangUtil; import com.dfsek.terra.config.lang.Language; import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.debug.DebugLogger; -import com.dfsek.terra.registry.ConfigRegistry; +import com.dfsek.terra.registry.master.AddonRegistry; +import com.dfsek.terra.registry.master.ConfigRegistry; import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.generation.MasterChunkGenerator; +import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D; import io.papermc.lib.PaperLib; import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; @@ -46,39 +60,50 @@ import java.util.Objects; public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin { - private final Map generatorMap = new HashMap<>(); + private final Map generatorMap = new HashMap<>(); private final Map worldMap = new HashMap<>(); private final Map worlds = new HashMap<>(); + private final ConfigRegistry registry = new ConfigRegistry(); + private final CheckedRegistry checkedRegistry = new CheckedRegistry<>(registry); + private final PluginConfig config = new PluginConfig(); private final ItemHandle itemHandle = new BukkitItemHandle(); private WorldHandle handle = new BukkitWorldHandle(); private final GenericLoaders genericLoaders = new GenericLoaders(this); private DebugLogger debugLogger; - private final EventManager eventManager = new TerraEventManager(this); - public static final Version BUKKIT_VERSION; + private final EventManager eventManager = new TerraEventManager(this); + public static final BukkitVersion BUKKIT_VERSION; static { String ver = Bukkit.getServer().getClass().getPackage().getName(); - if(ver.contains("1_16")) BUKKIT_VERSION = Version.V1_16; - else if(ver.contains("1_15")) BUKKIT_VERSION = Version.V1_15; - else if(ver.contains("1_14")) BUKKIT_VERSION = Version.V1_14; - else if(ver.contains("1_13")) BUKKIT_VERSION = Version.V1_13; - else BUKKIT_VERSION = Version.UNKNOWN; + if(ver.contains("1_16")) BUKKIT_VERSION = BukkitVersion.V1_16; + else if(ver.contains("1_15")) BUKKIT_VERSION = BukkitVersion.V1_15; + else if(ver.contains("1_14")) BUKKIT_VERSION = BukkitVersion.V1_14; + else if(ver.contains("1_13")) BUKKIT_VERSION = BukkitVersion.V1_13; + else BUKKIT_VERSION = BukkitVersion.UNKNOWN; } + private final AddonRegistry addonRegistry = new AddonRegistry(new BukkitAddon(this), this); + private final LockedRegistry addonLockedRegistry = new LockedRegistry<>(addonRegistry); - public void reload() { + + + public boolean reload() { + config.load(this); + LangUtil.load(config.getLanguage(), this); // Load language. + boolean succeed = registry.loadAll(this); Map newMap = new HashMap<>(); worldMap.forEach((world, tw) -> { - ((MasterChunkGenerator) ((BukkitChunkGeneratorWrapper) world.getGenerator().getHandle()).getHandle()).getCache().clear(); + tw.getConfig().getSamplerCache().clear(); String packID = tw.getConfig().getTemplate().getID(); newMap.put(world, new TerraWorld(world, registry.get(packID), this)); }); worldMap.clear(); worldMap.putAll(newMap); + return succeed; } @Override @@ -111,6 +136,11 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin { return eventManager; } + @Override + public void runPossiblyUnsafeTask(Runnable task) { + Bukkit.getScheduler().runTask(this, task); + } + @Override public void onDisable() { BukkitChunkGeneratorWrapper.saveAll(); @@ -118,12 +148,10 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin { @Override public void onEnable() { - debugLogger = new DebugLogger(getLogger()); - - eventManager.registerListener(new TerraListener(this)); // Register tree injection event + debugLogger = new DebugLogger(logger()); getLogger().info("Running on version " + BUKKIT_VERSION); - if(BUKKIT_VERSION.equals(Version.UNKNOWN)) { + if(BUKKIT_VERSION == BukkitVersion.UNKNOWN) { getLogger().warning("Terra is running on an unknown Bukkit version. Proceed with caution."); } @@ -136,18 +164,36 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin { LangUtil.load(config.getLanguage(), this); // Load language. debugLogger.setDebug(isDebug()); + if(!addonRegistry.loadAll()) { + getLogger().severe("Failed to load addons. Please correct addon installations to continue."); + Bukkit.getPluginManager().disablePlugin(this); + return; + } + registry.loadAll(this); // Load all config packs. PluginCommand c = Objects.requireNonNull(getCommand("terra")); - TerraCommand command = new TerraCommand(this); // Set up main Terra command. + + CommandManager manager = new TerraCommandManager(this); + + + try { + CommandUtil.registerAll(manager); + manager.register("save-data", SaveDataCommand.class); + manager.register("fix-chunk", FixChunkCommand.class); + } catch(MalformedCommandException e) { // This should never happen. + logger().severe("Errors occurred while registering commands."); + e.printStackTrace(); + logger().severe("Please report this to Terra."); + Bukkit.getPluginManager().disablePlugin(this); + return; + } + + BukkitCommandAdapter command = new BukkitCommandAdapter(manager); + c.setExecutor(command); c.setTabCompleter(command); - LocateCommand locate = new LocateCommand(command); - PluginCommand locatePl = Objects.requireNonNull(getCommand("locate")); - locatePl.setExecutor(locate); // Override locate command. Once Paper accepts StructureLocateEvent this will be unneeded on Paper implementations. - locatePl.setTabCompleter(locate); - long save = config.getDataSaveInterval(); Bukkit.getScheduler().runTaskTimerAsynchronously(this, BukkitChunkGeneratorWrapper::saveAll, save, save); // Schedule population data saving @@ -194,7 +240,7 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin { if(!registry.contains(id)) throw new IllegalArgumentException("No such config pack \"" + id + "\""); ConfigPack pack = registry.get(id); worlds.put(worldName, pack); - return new MasterChunkGenerator(registry.get(id), this, pack.getSamplerCache()); + return new DefaultChunkGenerator3D(registry.get(id), this); })); } @@ -209,8 +255,8 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin { return LangUtil.getLanguage(); } - public ConfigRegistry getRegistry() { - return registry; + public CheckedRegistry getConfigRegistry() { + return checkedRegistry; } public TerraWorld getWorld(World w) { @@ -218,11 +264,16 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin { throw new IllegalArgumentException("Not a Terra world! " + w.getGenerator()); if(!worlds.containsKey(w.getName())) { getLogger().warning("Unexpected world load detected: \"" + w.getName() + "\""); - return new TerraWorld(w, ((MasterChunkGenerator) w.getGenerator().getHandle()).getConfigPack(), this); + return new TerraWorld(w, ((TerraChunkGenerator) w.getGenerator().getHandle()).getConfigPack(), this); } return worldMap.computeIfAbsent(w, world -> new TerraWorld(w, worlds.get(w.getName()), this)); } + @Override + public Logger logger() { + return new JavaLogger(getLogger()); + } + @NotNull @Override public PluginConfig getTerraConfig() { @@ -239,13 +290,17 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin { public void register(TypeRegistry registry) { registry .registerLoader(BlockData.class, (t, o, l) -> handle.createBlockData((String) o)) - .registerLoader(MaterialData.class, (t, o, l) -> handle.createMaterialData((String) o)) .registerLoader(Biome.class, (t, o, l) -> new BukkitBiome(org.bukkit.block.Biome.valueOf((String) o))) .registerLoader(EntityType.class, (t, o, l) -> EntityType.valueOf((String) o)); genericLoaders.register(registry); } - public enum Version { + @Override + public LockedRegistry getAddons() { + return addonLockedRegistry; + } + + public enum BukkitVersion { V1_13(13), V1_14(14), @@ -258,7 +313,7 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin { private final int index; - Version(int index) { + BukkitVersion(int index) { this.index = index; } @@ -268,8 +323,24 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin { * @param other Other version * @return Whether this version is equal to or later than other. */ - public boolean above(Version other) { + public boolean above(BukkitVersion other) { return this.index >= other.index; } } + + @Addon("Terra-Bukkit") + @Version("1.0.0") + @Author("Terra") + private static final class BukkitAddon extends TerraAddon { + private final TerraPlugin main; + + private BukkitAddon(TerraPlugin main) { + this.main = main; + } + + @Override + public void initialize() { + main.getEventManager().registerListener(this, new TerraListener(main)); + } + } } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/BukkitCommandAdapter.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/BukkitCommandAdapter.java new file mode 100644 index 000000000..7a4d1227e --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/BukkitCommandAdapter.java @@ -0,0 +1,54 @@ +package com.dfsek.terra.bukkit.command; + +import com.dfsek.terra.api.command.CommandManager; +import com.dfsek.terra.api.command.exception.CommandException; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; + +public class BukkitCommandAdapter implements CommandExecutor, TabCompleter { + private final CommandManager manager; + + public BukkitCommandAdapter(CommandManager manager) { + this.manager = manager; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + List argList = new ArrayList<>(Arrays.asList(args)); + if(argList.isEmpty()) { + sender.sendMessage("Command requires arguments."); + return true; + } + try { + manager.execute(argList.remove(0), BukkitAdapter.adapt(sender), argList); + } catch(CommandException e) { + sender.sendMessage(e.getMessage()); + } + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + List argList = new ArrayList<>(Arrays.asList(args)); + + try { + return manager.tabComplete(argList.remove(0), BukkitAdapter.adapt(sender), argList).stream() + .filter(s -> s.toLowerCase(Locale.ROOT).startsWith(args[args.length - 1].toLowerCase(Locale.ROOT))).sorted(String::compareTo).collect(Collectors.toList()); + } catch(CommandException e) { + e.printStackTrace(); + return Collections.emptyList(); + } + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/Command.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/Command.java deleted file mode 100644 index 730389d76..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/Command.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.dfsek.terra.bukkit.command; - -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.bukkit.BukkitCommandSender; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Represents a command or subcommand, can be nested via getSubCommands. - */ -public abstract class Command implements CommandExecutor, TabCompleter { - private final TerraPlugin main; - public Command(TerraPlugin main) { - this.main = main; - } - public Command(Command parent) { - main = parent.getMain(); - } - - public TerraPlugin getMain() { - return main; - } - - /** - * Gets the name of the command/subcommand - * @return Name of command - */ - public abstract String getName(); - - /** - * Gets a list of subcommands - * @return List of subcommands - */ - public abstract List getSubCommands(); - - /** - * Executes the given command, returning its success. - *
- * If false is returned, then the "usage" plugin.yml entry for this command - * (if defined) will be sent to the player. - * - * @param sender Source of the command - * @param command Command which was executed - * @param label Alias of the command which was used - * @param args Passed command arguments - * @return true if a valid command, otherwise false - */ - - public abstract boolean execute(@NotNull CommandSender sender, @NotNull org.bukkit.command.Command command, @NotNull String label, @NotNull String[] args); - /** - * Gets the number of arguments - * @return Number of arguments - */ - public abstract int arguments(); - - /** - * Executes the given command, invoking subcommands if applicable and returning its success. - *
- * If false is returned, then the "usage" plugin.yml entry for this command - * (if defined) will be sent to the player. - * - * @param sender Source of the command - * @param command Command which was executed - * @param label Alias of the command which was used - * @param args Passed command arguments - * @return true if a valid command, otherwise false - */ - @Override - public final boolean onCommand(@NotNull CommandSender sender, @NotNull org.bukkit.command.Command command, @NotNull String label, @NotNull String[] args) { - if(this instanceof DebugCommand && ! main.isDebug()) { - main.getLanguage().send("command.debug-only", new BukkitCommandSender(sender)); - return true; - } - if(args.length > 0) { - for(Command c : getSubCommands()) { - if(c.getName().equals(args[0])) { - return c.onCommand(sender, command, label, Arrays.stream(args, 1, args.length).toArray(String[]::new)); - } - } - if(args.length != arguments()) { - main.getLanguage().send("command.invalid", new BukkitCommandSender(sender), String.valueOf(arguments()), String.valueOf(args.length)); - return true; - } - return execute(sender, command, label, args); - } - if(args.length != arguments()) { - main.getLanguage().send("command.invalid", new BukkitCommandSender(sender), String.valueOf(arguments()), String.valueOf(args.length)); - return true; - } - return execute(sender, command, label, new String[] {}); - } - - public abstract List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args); - - @Override - public final @Nullable List onTabComplete(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String alias, @NotNull String[] args) { - List complete = new ArrayList<>(); - if(args.length > 0) for(Command c : getSubCommands()) { - if(c.getName().startsWith(args[0])) complete.add(c.getName()); - if(c.getName().equals(args[0])) return c.onTabComplete(sender, command, alias, Arrays.stream(args, 1, args.length).toArray(String[]::new)); - } - complete.addAll(getTabCompletions(sender, alias, args)); - return complete; - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/DebugCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/DebugCommand.java deleted file mode 100644 index 738dde4fc..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/DebugCommand.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.dfsek.terra.bukkit.command; - -/** - * Implementing this interface marks a command as debug-only. - * If a parent command implements this interface, all child commands will be considered debug commands, regardless of whether they implement DebugCommand as well. - */ -public interface DebugCommand { -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/FixChunkCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/FixChunkCommand.java new file mode 100644 index 000000000..87d69c115 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/FixChunkCommand.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.bukkit.command; + +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; + +@Command +@WorldCommand +@PlayerCommand +public class FixChunkCommand implements CommandTemplate { + @Override + public void execute(CommandSender sender) { + Player player = (Player) sender; + BukkitChunkGeneratorWrapper.fixChunk(player.getWorld().getChunkAt(player.getLocation())); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/PlayerCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/PlayerCommand.java deleted file mode 100644 index 4f19eb741..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/PlayerCommand.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.dfsek.terra.bukkit.command; - -import com.dfsek.terra.bukkit.BukkitCommandSender; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -/** - * A command that may only be executed by a player. If executor is not a player, a message will be displayed and no action will be performed. - */ -public abstract class PlayerCommand extends Command { - public PlayerCommand(Command parent) { - super(parent); - } - - /** - * Executes the given command, returning its success. - *
- * If false is returned, then the "usage" plugin.yml entry for this command - * (if defined) will be sent to the player. - * - * @param sender Source of the command - * @param command Command which was executed - * @param label Alias of the command which was used - * @param args Passed command arguments - * @return true if a valid command, otherwise false - */ - @Override - public final boolean execute(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args) { - if(!(sender instanceof Player)) { - getMain().getLanguage().send("command.players-only", new BukkitCommandSender(sender)); - return true; - } - Player p = (Player) sender; - return execute(p, command, label, args); - } - /** - * Executes the given command, returning its success. - *
- * If false is returned, then the "usage" plugin.yml entry for this command - * (if defined) will be sent to the player. - * - * @param sender Player that executed command - * @param command Command which was executed - * @param label Alias of the command which was used - * @param args Passed command arguments - * @return true if a valid command, otherwise false - */ - public abstract boolean execute(@NotNull Player sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args); -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/SaveDataCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/SaveDataCommand.java new file mode 100644 index 000000000..4648cb01e --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/SaveDataCommand.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.bukkit.command; + +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; +import com.dfsek.terra.config.lang.LangUtil; + +@Command +public class SaveDataCommand implements CommandTemplate { + @Override + public void execute(CommandSender sender) { + BukkitChunkGeneratorWrapper.saveAll(); + LangUtil.send("debug.data-save", sender); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/WorldCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/WorldCommand.java deleted file mode 100644 index 65738d220..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/WorldCommand.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.dfsek.terra.bukkit.command; - -import com.dfsek.terra.bukkit.BukkitCommandSender; -import org.bukkit.World; -import org.bukkit.entity.Player; -import org.bukkit.generator.ChunkGenerator; -import org.jetbrains.annotations.NotNull; - -/** - * A command that must be executed by a player, in a Terra world. - */ -public abstract class WorldCommand extends PlayerCommand { - public WorldCommand(Command parent) { - super(parent); - } - - /** - * Executes the given command, returning its success. - *
- * If false is returned, then the "usage" plugin.yml entry for this command - * (if defined) will be sent to the player. - * - * @param sender Source of the command - * @param command Command which was executed - * @param label Alias of the command which was used - * @param args Passed command arguments - * @return true if a valid command, otherwise false - */ - @Override - public boolean execute(@NotNull Player sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args) { - if(sender.getWorld().getGenerator() instanceof ChunkGenerator) { // TODO: implementation - return execute(sender, command, label, args, sender.getWorld()); - } else { - getMain().getLanguage().send("command.world", new BukkitCommandSender(sender)); - } - return true; - } - - /** - * Executes the given command, returning its success. - *
- * If false is returned, then the "usage" plugin.yml entry for this command - * (if defined) will be sent to the player. - * - * @param sender Player that executed command - * @param command Command which was executed - * @param label Alias of the command which was used - * @param args Passed command arguments - * @param world World in which command was executed - * @return true if a valid command, otherwise false - */ - public abstract boolean execute(@NotNull Player sender, @NotNull org.bukkit.command.Command command, @NotNull String label, @NotNull String[] args, World world); -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/FixChunkCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/FixChunkCommand.java deleted file mode 100644 index 4b9d730d7..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/FixChunkCommand.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.dfsek.terra.bukkit.command.command; - -import com.dfsek.terra.bukkit.command.WorldCommand; -import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -public class FixChunkCommand extends WorldCommand { - public FixChunkCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player player, @NotNull Command command, @NotNull String s, @NotNull String[] strings, World world) { - BukkitChunkGeneratorWrapper.fixChunk(BukkitAdapter.adapt(player.getLocation().getChunk())); - return true; - } - - @Override - public String getName() { - return "fixchunk"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 0; - } - - @Override - public List getTabCompletions(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] strings) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/GetBlockCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/GetBlockCommand.java deleted file mode 100644 index 2585430c6..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/GetBlockCommand.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.dfsek.terra.bukkit.command.command; - -import com.dfsek.terra.bukkit.command.WorldCommand; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -public class GetBlockCommand extends WorldCommand { - public GetBlockCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player player, @NotNull Command command, @NotNull String s, @NotNull String[] strings, World world) { - player.sendMessage("Block: " + getMain().getWorld(BukkitAdapter.adapt(world)).getUngeneratedBlock(BukkitAdapter.adapt(player.getLocation())).getAsString()); - return true; - } - - @Override - public String getName() { - return "block"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 0; - } - - @Override - public List getTabCompletions(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] strings) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/PacksCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/PacksCommand.java deleted file mode 100644 index ce768d37a..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/PacksCommand.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.dfsek.terra.bukkit.command.command; - -import com.dfsek.terra.bukkit.BukkitCommandSender; -import com.dfsek.terra.bukkit.command.Command; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.config.pack.ConfigPackTemplate; -import com.dfsek.terra.registry.ConfigRegistry; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -public class PacksCommand extends Command { - public PacksCommand(Command parent) { - super(parent); - } - - @Override - public String getName() { - return "packs"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public boolean execute(@NotNull CommandSender commandSender, org.bukkit.command.@NotNull Command command, @NotNull String s, @NotNull String[] strings) { - - ConfigRegistry registry = getMain().getRegistry(); - - if(registry.entries().size() == 0) { - LangUtil.send("command.packs.none", new BukkitCommandSender(commandSender)); - return true; - } - - LangUtil.send("command.packs.main", new BukkitCommandSender(commandSender)); - registry.entries().forEach(entry -> { - ConfigPackTemplate template = entry.getTemplate(); - LangUtil.send("command.packs.pack", new BukkitCommandSender(commandSender), template.getID(), template.getAuthor(), template.getVersion()); - }); - - return true; - } - - @Override - public int arguments() { - return 0; - } - - @Override - public List getTabCompletions(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] strings) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/ReloadCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/ReloadCommand.java deleted file mode 100644 index b6b4093ac..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/ReloadCommand.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.dfsek.terra.bukkit.command.command; - - -import com.dfsek.terra.bukkit.BukkitCommandSender; -import com.dfsek.terra.bukkit.command.Command; -import com.dfsek.terra.bukkit.command.DebugCommand; -import com.dfsek.terra.config.lang.LangUtil; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -public class ReloadCommand extends Command implements DebugCommand { - public ReloadCommand(Command parent) { - super(parent); - } - - @Override - public String getName() { - return "reload"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public boolean execute(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args) { - getMain().getTerraConfig().load(getMain()); - LangUtil.load(getMain().getTerraConfig().getLanguage(), getMain()); // Load language. - if(!getMain().getRegistry().loadAll(getMain())) { - LangUtil.send("command.reload-error", new BukkitCommandSender(sender)); - return true; - } - getMain().reload(); - LangUtil.send("command.reload", new BukkitCommandSender(sender)); - return true; - } - - @Override - public int arguments() { - return 0; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/SaveDataCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/SaveDataCommand.java deleted file mode 100644 index 4cb09daba..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/SaveDataCommand.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.dfsek.terra.bukkit.command.command; - -import com.dfsek.terra.bukkit.BukkitCommandSender; -import com.dfsek.terra.bukkit.command.Command; -import com.dfsek.terra.bukkit.command.WorldCommand; -import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; -import com.dfsek.terra.config.lang.LangUtil; -import org.bukkit.World; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -public class SaveDataCommand extends WorldCommand { - public SaveDataCommand(Command parent) { - super(parent); - } - - @Override - public String getName() { - return "save-data"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 0; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } - - @Override - public boolean execute(@NotNull Player sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args, World w) { - BukkitChunkGeneratorWrapper.saveAll(); - LangUtil.send("debug.data-save", new BukkitCommandSender(sender), w.getName()); - return true; - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/TerraCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/TerraCommand.java deleted file mode 100644 index 6a1948cf9..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/TerraCommand.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.dfsek.terra.bukkit.command.command; - -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.bukkit.BukkitCommandSender; -import com.dfsek.terra.bukkit.command.Command; -import com.dfsek.terra.bukkit.command.command.biome.BiomeCommand; -import com.dfsek.terra.bukkit.command.command.geometry.GeometryCommand; -import com.dfsek.terra.bukkit.command.command.profile.ProfileCommand; -import com.dfsek.terra.bukkit.command.command.structure.StructureCommand; -import com.dfsek.terra.config.lang.LangUtil; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -public class TerraCommand extends Command { - private final List commands = Arrays.asList(new ReloadCommand(this), - new BiomeCommand(this), - new ProfileCommand(this), - new SaveDataCommand(this), - new StructureCommand(this), - new GeometryCommand(this), - new FixChunkCommand(this), - new VersionCommand(this), - new GetBlockCommand(this), - new PacksCommand(this)); - - public TerraCommand(TerraPlugin main) { - super(main); - } - - @Override - public String getName() { - return "terra"; - } - - @Override - public List getSubCommands() { - return commands; - } - - @Override - public boolean execute(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args) { - LangUtil.send("command.main-menu", new BukkitCommandSender(sender)); - return true; - } - - @Override - public int arguments() { - return 0; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/VersionCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/VersionCommand.java deleted file mode 100644 index b9686d186..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/VersionCommand.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.dfsek.terra.bukkit.command.command; - -import com.dfsek.terra.bukkit.BukkitCommandSender; -import com.dfsek.terra.bukkit.TerraBukkitPlugin; -import com.dfsek.terra.bukkit.command.Command; -import com.dfsek.terra.config.lang.LangUtil; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -public class VersionCommand extends Command { - public VersionCommand(Command parent) { - super(parent); - } - - @Override - public String getName() { - return "version"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public boolean execute(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args) { - String terraVersion = ((TerraBukkitPlugin) getMain()).getDescription().getVersion(); - LangUtil.send("command.version", new BukkitCommandSender(sender), terraVersion, getMain().platformName()); - return true; - } - - @Override - public int arguments() { - return 0; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeCommand.java deleted file mode 100644 index 254550157..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeCommand.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.biome; - -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.biome.provider.BiomeProvider; -import com.dfsek.terra.bukkit.command.WorldCommand; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.config.lang.LangUtil; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -public class BiomeCommand extends WorldCommand { - public BiomeCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World w) { - BiomeProvider grid = getMain().getWorld(BukkitAdapter.adapt(sender.getWorld())).getBiomeProvider(); - UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(BukkitAdapter.adapt(sender.getLocation())); - LangUtil.send("command.biome.in", BukkitAdapter.adapt(sender), biome.getID()); - return true; - } - - @Override - public String getName() { - return "biome"; - } - - @Override - public List getSubCommands() { - return Arrays.asList(new BiomeLocateCommand(this), new BiomeInfoCommand(this)); - } - - @Override - public int arguments() { - return 0; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeInfoCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeInfoCommand.java deleted file mode 100644 index 636907691..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeInfoCommand.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.biome; - -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.bukkit.BukkitCommandSender; -import com.dfsek.terra.bukkit.command.WorldCommand; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.population.items.TerraStructure; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -public class BiomeInfoCommand extends WorldCommand { - public BiomeInfoCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - String id = args[0]; - ConfigPack cfg = getMain().getWorld(BukkitAdapter.adapt(world)).getConfig(); - UserDefinedBiome b; - try { - b = (UserDefinedBiome) cfg.getBiome(id); - } catch(IllegalArgumentException | NullPointerException e) { - LangUtil.send("command.biome.invalid", new BukkitCommandSender(sender), id); - return true; - } - sender.sendMessage("TerraBiome info for \"" + b.getID() + "\"."); - sender.sendMessage("Vanilla biome: " + b.getVanillaBiomes()); - - BiomeTemplate bio = b.getConfig(); - - if(bio.getExtend() != null) sender.sendMessage("Extends: " + bio.getExtend()); - - List structureConfigs = bio.getStructures(); - - if(structureConfigs.size() == 0) sender.sendMessage("No Structures"); - else { - sender.sendMessage("-------Structures-------"); - for(TerraStructure c : structureConfigs) { - sender.sendMessage(" - " + c.getTemplate().getID()); - } - } - - return true; - } - - @Override - public String getName() { - return "info"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 1; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - if(!(sender instanceof Player) || !TerraWorld.isTerraWorld(BukkitAdapter.adapt(((Player) sender).getWorld()))) - return Collections.emptyList(); - List ids = getMain().getWorld(BukkitAdapter.adapt(((Player) sender).getWorld())).getConfig().getBiomeIDs(); - if(args.length == 1) - return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList()); - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeLocateCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeLocateCommand.java deleted file mode 100644 index 17d1abf59..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeLocateCommand.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.biome; - -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.async.AsyncBiomeFinder; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.bukkit.TerraBukkitPlugin; -import com.dfsek.terra.bukkit.command.WorldCommand; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.world.TerraWorld; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.ClickEvent; -import net.md_5.bungee.api.chat.ComponentBuilder; -import net.md_5.bungee.api.chat.HoverEvent; -import net.md_5.bungee.api.chat.TextComponent; -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -@SuppressWarnings("deprecation") -public class BiomeLocateCommand extends WorldCommand { - public BiomeLocateCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @SuppressWarnings("DuplicatedCode") - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - String id = args[0]; - int maxRadius; - try { - maxRadius = Integer.parseInt(args[1]); - } catch(NumberFormatException e) { - LangUtil.send("command.biome.invalid-radius", BukkitAdapter.adapt(sender), args[1]); - return true; - } - TerraBiome b; - try { - b = getMain().getWorld(BukkitAdapter.adapt(world)).getConfig().getBiome(id); - } catch(IllegalArgumentException | NullPointerException e) { - LangUtil.send("command.biome.invalid", BukkitAdapter.adapt(sender), id); - return true; - } - Bukkit.getScheduler().runTaskAsynchronously((TerraBukkitPlugin) getMain(), new AsyncBiomeFinder(getMain().getWorld(BukkitAdapter.adapt(world)).getBiomeProvider(), b, BukkitAdapter.adapt(sender.getLocation().clone().multiply((1D / ((TerraBukkitPlugin) getMain()).getTerraConfig().getBiomeSearchResolution()))), 0, maxRadius, location -> { - if(location != null) { - ComponentBuilder cm = new ComponentBuilder(String.format("The nearest %s is at ", id.toLowerCase())) - .append(String.format("[%d, ~, %d]", location.getBlockX(), location.getBlockZ()), ComponentBuilder.FormatRetention.NONE) - .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/minecraft:tp %s %d.0 %.2f %d.0", sender.getName(), location.getBlockX(), sender.getLocation().getY(), location.getBlockZ()))) - .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new BaseComponent[] {new TextComponent("Click to teleport")})) - .color(ChatColor.GREEN) - .append(String.format(" (%.1f blocks away)", location.add(new Vector3(0, sender.getLocation().getY(), 0)).distance(BukkitAdapter.adapt(sender.getLocation().toVector()))), ComponentBuilder.FormatRetention.NONE); - sender.spigot().sendMessage(cm.create()); - // LangUtil.send("command.biome.biome-found", sender, String.valueOf(location.getBlockX()), String.valueOf(location.getBlockZ())); - } else LangUtil.send("command.biome.unable-to-locate", BukkitAdapter.adapt(sender)); - }, getMain())); - - return true; - } - - @Override - public String getName() { - return "locate"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 2; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - if(!(sender instanceof Player) || !TerraWorld.isTerraWorld(BukkitAdapter.adapt(((Player) sender).getWorld()))) - return Collections.emptyList(); - List ids = getMain().getWorld(BukkitAdapter.adapt(((Player) sender).getWorld())).getConfig().getBiomeIDs(); - if(args.length == 1) - return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList()); - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/DeformedSphereCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/DeformedSphereCommand.java deleted file mode 100644 index 716f28517..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/DeformedSphereCommand.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.geometry; - -import com.dfsek.terra.api.math.noise.samplers.noise.simplex.OpenSimplex2Sampler; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.math.voxel.DeformedSphere; -import com.dfsek.terra.bukkit.BukkitCommandSender; -import com.dfsek.terra.bukkit.command.PlayerCommand; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.config.lang.LangUtil; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -public class DeformedSphereCommand extends PlayerCommand { - public DeformedSphereCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - int radius; - try { - radius = Integer.parseInt(args[0]); - } catch(NumberFormatException e) { - LangUtil.send("command.geometry.deform.invalid-radius", new BukkitCommandSender(sender), args[0]); - return true; - } - double deform; - try { - deform = Double.parseDouble(args[1]); - } catch(NumberFormatException e) { - LangUtil.send("command.geometry.deform.invalid-deform", new BukkitCommandSender(sender), args[1]); - return true; - } - - double freq; - try { - freq = Float.parseFloat(args[2]); - } catch(NumberFormatException e) { - LangUtil.send("command.geometry.deform.invalid-frequency", new BukkitCommandSender(sender), args[2]); - return true; - } - OpenSimplex2Sampler n = new OpenSimplex2Sampler((int) sender.getWorld().getSeed()); - n.setFrequency(freq); - DeformedSphere sphere = new DeformedSphere(BukkitAdapter.adapt(sender).getLocation().toVector(), radius, deform, n); - for(Vector3 v : sphere.getGeometry()) { - v.toLocation(BukkitAdapter.adapt(sender.getWorld())).getBlock().setBlockData(getMain().getWorldHandle().createBlockData("minecraft:stone"), false); - } - return true; - } - - @Override - public String getName() { - return "deformedsphere"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 3; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/GeometryCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/GeometryCommand.java deleted file mode 100644 index 8e9b2d89e..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/GeometryCommand.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.geometry; - -import com.dfsek.terra.bukkit.BukkitCommandSender; -import com.dfsek.terra.bukkit.command.DebugCommand; -import com.dfsek.terra.bukkit.command.PlayerCommand; -import com.dfsek.terra.config.lang.LangUtil; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -public class GeometryCommand extends PlayerCommand implements DebugCommand { - public GeometryCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - LangUtil.send("command.geometry.main-menu", new BukkitCommandSender(sender)); - return true; - } - - @Override - public String getName() { - return "geometry"; - } - - @Override - public List getSubCommands() { - return Arrays.asList(new SphereCommand(this), new TubeCommand(this), new DeformedSphereCommand(this)); - } - - @Override - public int arguments() { - return 0; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/SphereCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/SphereCommand.java deleted file mode 100644 index a726d7b02..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/SphereCommand.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.geometry; - -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.math.voxel.Sphere; -import com.dfsek.terra.bukkit.BukkitCommandSender; -import com.dfsek.terra.bukkit.BukkitPlayer; -import com.dfsek.terra.bukkit.command.PlayerCommand; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.config.lang.LangUtil; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -public class SphereCommand extends PlayerCommand { - public SphereCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - int radius; - try { - radius = Integer.parseInt(args[0]); - } catch(NumberFormatException e) { - LangUtil.send("command.geometry.sphere.invalid-radius", new BukkitCommandSender(sender), args[0]); - return true; - } - Sphere sphere = new Sphere(new BukkitPlayer(sender).getLocation().toVector(), radius); - for(Vector3 v : sphere.getGeometry()) { - v.toLocation(BukkitAdapter.adapt(sender.getWorld())).getBlock().setBlockData(getMain().getWorldHandle().createBlockData("minecraft:stone"), false); - } - return true; - } - - @Override - public String getName() { - return "sphere"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 1; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/TubeCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/TubeCommand.java deleted file mode 100644 index 33bd17ad5..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/TubeCommand.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.geometry; - -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.math.voxel.Tube; -import com.dfsek.terra.bukkit.BukkitCommandSender; -import com.dfsek.terra.bukkit.command.PlayerCommand; -import com.dfsek.terra.bukkit.structure.WorldEditUtil; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.config.lang.LangUtil; -import org.bukkit.Location; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -public class TubeCommand extends PlayerCommand { - public TubeCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - Location[] l = WorldEditUtil.getSelectionPositions(sender); - if(l == null) return true; - int radius; - try { - radius = Integer.parseInt(args[0]); - } catch(NumberFormatException e) { - LangUtil.send("command.geometry.tube.invalid-radius", new BukkitCommandSender(sender), args[0]); - return true; - } - Tube tube = new Tube(BukkitAdapter.adapt(l[0].toVector()), BukkitAdapter.adapt(l[1].toVector()), radius); - for(Vector3 v : tube.getGeometry()) { - v.toLocation(BukkitAdapter.adapt(sender.getWorld())).getBlock().setBlockData(getMain().getWorldHandle().createBlockData("minecraft:stone"), false); - } - return true; - } - - @Override - public String getName() { - return "tube"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 1; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/ProfileCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/ProfileCommand.java deleted file mode 100644 index 5eb4b4ec1..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/ProfileCommand.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.profile; - -import com.dfsek.terra.bukkit.BukkitCommandSender; -import com.dfsek.terra.bukkit.command.WorldCommand; -import com.dfsek.terra.config.lang.LangUtil; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -public class ProfileCommand extends WorldCommand { - public ProfileCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World w) { - LangUtil.send("command.profile.main-menu", new BukkitCommandSender(sender)); - return true; - } - - @Override - public String getName() { - return "profile"; - } - - @Override - public List getSubCommands() { - return Arrays.asList(new QueryCommand(this), new ResetCommand(this), new StartCommand(this), new StopCommand(this)); - } - - @Override - public int arguments() { - return 1; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/QueryCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/QueryCommand.java deleted file mode 100644 index b958b83cb..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/QueryCommand.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.profile; - -import com.dfsek.terra.bukkit.command.WorldCommand; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.profiler.WorldProfiler; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -public class QueryCommand extends WorldCommand { - public QueryCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - WorldProfiler profile = getMain().getWorld(BukkitAdapter.adapt(world)).getProfiler(); - sender.sendMessage(profile.getResultsFormatted()); - return true; - } - - @Override - public String getName() { - return "query"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 0; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/ResetCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/ResetCommand.java deleted file mode 100644 index 958b48eb4..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/ResetCommand.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.profile; - -import com.dfsek.terra.bukkit.BukkitCommandSender; -import com.dfsek.terra.bukkit.command.WorldCommand; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.profiler.WorldProfiler; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -public class ResetCommand extends WorldCommand { - public ResetCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - WorldProfiler profile = getMain().getWorld(BukkitAdapter.adapt(world)).getProfiler(); - profile.reset(); - LangUtil.send("command.profile.reset", new BukkitCommandSender(sender)); - return true; - } - - @Override - public String getName() { - return "reset"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 0; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/StartCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/StartCommand.java deleted file mode 100644 index bdd5055d4..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/StartCommand.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.profile; - -import com.dfsek.terra.bukkit.BukkitCommandSender; -import com.dfsek.terra.bukkit.command.WorldCommand; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.profiler.WorldProfiler; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -public class StartCommand extends WorldCommand { - public StartCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - WorldProfiler profile = getMain().getWorld(BukkitAdapter.adapt(world)).getProfiler(); - profile.setProfiling(true); - LangUtil.send("command.profile.start", new BukkitCommandSender(sender)); - return true; - } - - @Override - public String getName() { - return "start"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 0; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/StopCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/StopCommand.java deleted file mode 100644 index 322cff032..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/StopCommand.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.profile; - -import com.dfsek.terra.bukkit.BukkitCommandSender; -import com.dfsek.terra.bukkit.command.WorldCommand; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.profiler.WorldProfiler; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -public class StopCommand extends WorldCommand { - public StopCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - WorldProfiler profile = getMain().getWorld(BukkitAdapter.adapt(world)).getProfiler(); - profile.setProfiling(false); - LangUtil.send("command.profile.stop", new BukkitCommandSender(sender)); - return true; - } - - @Override - public String getName() { - return "stop"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 0; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/LocateCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/LocateCommand.java deleted file mode 100644 index 933895da6..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/LocateCommand.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.structure; - -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.async.AsyncStructureFinder; -import com.dfsek.terra.bukkit.TerraBukkitPlugin; -import com.dfsek.terra.bukkit.command.WorldCommand; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.population.items.TerraStructure; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.ClickEvent; -import net.md_5.bungee.api.chat.ComponentBuilder; -import net.md_5.bungee.api.chat.HoverEvent; -import net.md_5.bungee.api.chat.TextComponent; -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -public class LocateCommand extends WorldCommand { - - public LocateCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @SuppressWarnings({"DuplicatedCode", "deprecation"}) - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - String id = args[0]; - int maxRadius; - - try { - maxRadius = Integer.parseInt(args[1]); - } catch(NumberFormatException e) { - LangUtil.send("command.structure.invalid-radius", BukkitAdapter.adapt(sender), args[1]); - return true; - } - TerraStructure s; - try { - s = Objects.requireNonNull(getMain().getWorld(BukkitAdapter.adapt(world)).getConfig().getStructure(id)); - } catch(IllegalArgumentException | NullPointerException e) { - LangUtil.send("command.structure.invalid", BukkitAdapter.adapt(sender), id); - return true; - } - Bukkit.getScheduler().runTaskAsynchronously((TerraBukkitPlugin) getMain(), new AsyncStructureFinder(getMain().getWorld(BukkitAdapter.adapt(world)).getBiomeProvider(), s, BukkitAdapter.adapt(sender.getLocation()), 0, maxRadius, (location) -> { - if(sender.isOnline()) { - if(location != null) { - ComponentBuilder cm = new ComponentBuilder(String.format("The nearest %s is at ", id.toLowerCase())) - .append(String.format("[%d, ~, %d]", location.getBlockX(), location.getBlockZ()), ComponentBuilder.FormatRetention.NONE) - .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/minecraft:tp %s %d.0 %.2f %d.0", sender.getName(), location.getBlockX(), sender.getLocation().getY(), location.getBlockZ()))) - .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new BaseComponent[] {new TextComponent("Click to teleport")})) - .color(ChatColor.GREEN) - .append(String.format(" (%.1f blocks away)", location.add(new Vector3(0, sender.getLocation().getY(), 0)).distance( - BukkitAdapter.adapt(sender.getLocation().toVector()))), ComponentBuilder.FormatRetention.NONE); - sender.spigot().sendMessage(cm.create()); - } else - sender.sendMessage("Unable to locate structure. "); - } - }, getMain())); - - return true; - } - - @Override - public String getName() { - return "locate"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 2; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - if(!(sender instanceof Player) || !(TerraWorld.isTerraWorld(BukkitAdapter.adapt(((Player) sender).getWorld())))) - return Collections.emptyList(); - - List ids = getMain().getWorld(BukkitAdapter.adapt(((Player) sender).getWorld())).getConfig().getStructureIDs(); - if(args.length == 1) - return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList()); - - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/SpawnCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/SpawnCommand.java deleted file mode 100644 index 0c78c10ce..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/SpawnCommand.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.structure; - -import com.dfsek.terra.api.structures.parser.lang.constants.NumericConstant; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.script.functions.CheckFunction; -import com.dfsek.terra.api.structures.structure.Rotation; -import com.dfsek.terra.api.structures.structure.buffer.StructureBuffer; -import com.dfsek.terra.api.structures.tokenizer.Position; -import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.bukkit.command.DebugCommand; -import com.dfsek.terra.bukkit.command.WorldCommand; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; - -public class SpawnCommand extends WorldCommand implements DebugCommand { - public SpawnCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - Location p = sender.getLocation(); - int x = p.getBlockX(); - int y = p.getBlockY(); - int z = p.getBlockZ(); - Position dummy = new Position(0, 0); - com.dfsek.terra.api.platform.world.World w = BukkitAdapter.adapt(world); - String check = new CheckFunction(getMain(), new NumericConstant(0, dummy), new NumericConstant(0, dummy), new NumericConstant(0, dummy), getMain().getWorld(w).getConfig().getSamplerCache(), dummy).apply(new TerraImplementationArguments(new StructureBuffer( - new com.dfsek.terra.api.math.vector.Location(w, x, y, z) - ), Rotation.NONE, new FastRandom(), 0), new HashMap<>()); - - sender.sendMessage("Found: " + check); - return true; - } - - @Override - public String getName() { - return "spawn"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 0; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/StructureCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/StructureCommand.java deleted file mode 100644 index 16c6b277a..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/StructureCommand.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.structure; - -import com.dfsek.terra.bukkit.BukkitCommandSender; -import com.dfsek.terra.bukkit.command.PlayerCommand; -import com.dfsek.terra.bukkit.command.command.structure.load.LoadCommand; -import com.dfsek.terra.config.lang.LangUtil; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -public class StructureCommand extends PlayerCommand { - public StructureCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - LangUtil.send("command.structure.main-menu", new BukkitCommandSender(sender)); - return true; - } - - @Override - public String getName() { - return "structure"; - } - - @Override - public List getSubCommands() { - return Arrays.asList(new ExportCommand(this), new LoadCommand(this), new LocateCommand(this), new SpawnCommand(this)); - } - - @Override - public int arguments() { - return 0; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadCommand.java deleted file mode 100644 index c8a88e325..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadCommand.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.structure.load; - -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.bukkit.command.DebugCommand; -import com.dfsek.terra.bukkit.command.PlayerCommand; -import com.dfsek.terra.world.TerraWorld; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -public class LoadCommand extends PlayerCommand implements DebugCommand { - public LoadCommand(com.dfsek.terra.bukkit.command.Command parent) { - super(parent); - } - - public List getStructureNames(World world) { - List names = new ArrayList<>(); - TerraWorld terraWorld = getMain().getWorld(world); - - terraWorld.getConfig().getScriptRegistry().forEach(script -> names.add(script.getId())); - - return names; - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - return true; - } - - @Override - public String getName() { - return "load"; - } - - @Override - public List getSubCommands() { - return Arrays.asList(new LoadFullCommand(this, true), new LoadFullCommand(this, false)); - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 0; - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadFullCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadFullCommand.java deleted file mode 100644 index 0bbf7969a..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadFullCommand.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.dfsek.terra.bukkit.command.command.structure.load; - -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.api.structures.structure.Rotation; -import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.bukkit.command.DebugCommand; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.bukkit.world.BukkitChunk; -import com.dfsek.terra.util.PopulationUtil; -import com.dfsek.terra.world.TerraWorld; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class LoadFullCommand extends LoadCommand implements DebugCommand { - private final boolean chunk; - - public LoadFullCommand(com.dfsek.terra.bukkit.command.Command parent, boolean chunk) { - super(parent); - this.chunk = chunk; - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) { - TerraWorld terraWorld = getMain().getWorld(BukkitAdapter.adapt(sender.getWorld())); - long t = System.nanoTime(); - FastRandom chunk = PopulationUtil.getRandom(new BukkitChunk(sender.getLocation().getChunk())); - Rotation r; - try { - r = Rotation.fromDegrees(Integer.parseInt(args[1])); - } catch(Exception e) { - sender.sendMessage("Invalid rotation: " + args[1]); - return true; - } - StructureScript script = terraWorld.getConfig().getScriptRegistry().get(args[0]); - if(script == null) { - sender.sendMessage("Invalid structure: " + args[0]); - return true; - } - if(this.chunk) { - script.execute(BukkitAdapter.adapt(sender.getLocation()), BukkitAdapter.adapt(sender.getLocation().getChunk()), chunk, r); - } else { - script.execute(BukkitAdapter.adapt(sender.getLocation()), chunk, r); - } - long l = System.nanoTime() - t; - - sender.sendMessage("Took " + ((double) l) / 1000000 + "ms"); - return true; - } - - @Override - public String getName() { - return chunk ? "chunk" : "full"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 2; - } - - @Override - public List getTabCompletions(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] args) { - World w = BukkitAdapter.adapt(((Player) commandSender).getWorld()); - if(!TerraWorld.isTerraWorld(w)) return Collections.emptyList(); - switch(args.length) { - case 1: - return getMain().getWorld(w).getConfig().getScriptRegistry().entries().stream().map(StructureScript::getId).filter(id -> id.startsWith(args[0])).sorted().collect(Collectors.toList()); - case 2: - return Stream.of("0", "90", "180", "270").filter(string -> string.toUpperCase().startsWith(args[1].toUpperCase())).collect(Collectors.toList()); - } - return Collections.emptyList(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGenerator.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGenerator.java index b1875f1ff..da186a425 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGenerator.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGenerator.java @@ -1,20 +1,10 @@ package com.dfsek.terra.bukkit.generator; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.BiomeGrid; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.BlockPopulator; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import com.dfsek.terra.bukkit.world.BukkitBiomeGrid; -import com.dfsek.terra.bukkit.world.BukkitWorld; +import com.dfsek.terra.api.platform.world.generator.ChunkData; import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData; import org.bukkit.generator.ChunkGenerator; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.Random; -import java.util.stream.Collectors; public class BukkitChunkGenerator implements com.dfsek.terra.api.platform.world.generator.ChunkGenerator { private final ChunkGenerator delegate; @@ -28,46 +18,6 @@ public class BukkitChunkGenerator implements com.dfsek.terra.api.platform.world. return delegate; } - @Override - public boolean isParallelCapable() { - return delegate.isParallelCapable(); - } - - @Override - public boolean shouldGenerateCaves() { - return delegate.shouldGenerateCaves(); - } - - @Override - public boolean shouldGenerateDecorations() { - return delegate.shouldGenerateDecorations(); - } - - @Override - public boolean shouldGenerateMobs() { - return delegate.shouldGenerateMobs(); - } - - @Override - public boolean shouldGenerateStructures() { - return delegate.shouldGenerateStructures(); - } - - @Override - public ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome) { - return new BukkitChunkData(delegate.generateChunkData(((BukkitWorld) world).getHandle(), random, x, z, ((BukkitBiomeGrid) biome).getHandle())); - } - - @Override - public List getDefaultPopulators(World world) { - return delegate.getDefaultPopulators(((BukkitWorld) world).getHandle()).stream().map(BukkitPopulator::new).collect(Collectors.toList()); - } - - @Override - public @Nullable TerraChunkGenerator getTerraGenerator() { - return delegate instanceof BukkitChunkGeneratorWrapper ? ((BukkitChunkGeneratorWrapper) delegate).getHandle() : null; - } - public static class BukkitChunkData implements ChunkData { private final ChunkGenerator.ChunkData delegate; diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java index b8bb83839..092b486f2 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java @@ -1,6 +1,6 @@ package com.dfsek.terra.bukkit.generator; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; import com.dfsek.terra.api.world.generation.TerraBlockPopulator; @@ -8,11 +8,10 @@ import com.dfsek.terra.api.world.generation.TerraChunkGenerator; import com.dfsek.terra.bukkit.population.PopulationManager; import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.bukkit.world.BukkitBiomeGrid; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.population.CavePopulator; import com.dfsek.terra.profiler.DataType; import com.dfsek.terra.profiler.Measurement; import com.dfsek.terra.world.TerraWorld; +import com.dfsek.terra.world.population.CavePopulator; import com.dfsek.terra.world.population.FloraPopulator; import com.dfsek.terra.world.population.OrePopulator; import com.dfsek.terra.world.population.StructurePopulator; @@ -29,7 +28,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Random; -import java.util.logging.Level; import java.util.stream.Collectors; public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper { @@ -77,8 +75,8 @@ public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements Gener private void load(com.dfsek.terra.api.platform.world.World w) { try { popMan.loadBlocks(w); - } catch(FileNotFoundException e) { - LangUtil.log("warning.no-population", Level.WARNING); + } catch(FileNotFoundException ignore) { + } catch(IOException | ClassNotFoundException e) { e.printStackTrace(); } @@ -123,7 +121,7 @@ public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements Gener @Override public boolean shouldGenerateStructures() { - return super.shouldGenerateStructures(); + return delegate.shouldGenerateStructures(); } @Override diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitItemHandle.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitItemHandle.java index aa8531e67..f13783203 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitItemHandle.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitItemHandle.java @@ -1,13 +1,11 @@ package com.dfsek.terra.bukkit.handles; -import com.dfsek.terra.api.platform.block.MaterialData; import com.dfsek.terra.api.platform.handle.ItemHandle; -import com.dfsek.terra.api.platform.inventory.ItemStack; +import com.dfsek.terra.api.platform.inventory.Item; import com.dfsek.terra.api.platform.inventory.item.Enchantment; import com.dfsek.terra.bukkit.util.MinecraftUtils; import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.bukkit.world.block.BukkitMaterialData; -import com.dfsek.terra.bukkit.world.inventory.BukkitItemStack; +import org.bukkit.Material; import org.bukkit.NamespacedKey; import java.util.Arrays; @@ -15,9 +13,10 @@ import java.util.Set; import java.util.stream.Collectors; public class BukkitItemHandle implements ItemHandle { + @Override - public ItemStack newItemStack(MaterialData material, int amount) { - return new BukkitItemStack(new org.bukkit.inventory.ItemStack(((BukkitMaterialData) material).getHandle(), amount)); + public Item createItem(String data) { + return BukkitAdapter.adapt(Material.matchMaterial(data)); } @Override diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java index 03beeabcb..8f3736103 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java @@ -1,31 +1,18 @@ package com.dfsek.terra.bukkit.handles; -import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; import com.dfsek.terra.api.platform.entity.EntityType; +import com.dfsek.terra.api.platform.entity.Player; import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.bukkit.world.block.BukkitMaterialData; +import com.dfsek.terra.api.util.generic.pair.Pair; +import com.dfsek.terra.bukkit.structure.WorldEditUtil; +import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData; import com.dfsek.terra.bukkit.world.entity.BukkitEntityType; import org.bukkit.Bukkit; -import org.bukkit.Material; public class BukkitWorldHandle implements WorldHandle { - @Override - public void setBlockData(Block block, BlockData data, boolean physics) { - block.setBlockData(data, physics); - } - - @Override - public BlockData getBlockData(Block block) { - return block.getBlockData(); - } - - @Override - public MaterialData getType(Block block) { - return block.getType(); - } @Override public BlockData createBlockData(String data) { @@ -33,13 +20,14 @@ public class BukkitWorldHandle implements WorldHandle { return BukkitBlockData.newInstance(bukkitData); } - @Override - public MaterialData createMaterialData(String data) { - return new BukkitMaterialData(Material.matchMaterial(data)); - } - @Override public EntityType getEntity(String id) { return new BukkitEntityType(org.bukkit.entity.EntityType.valueOf(id)); } + + @Override + public Pair getSelectedLocation(Player player) { + org.bukkit.Location[] locations = WorldEditUtil.getSelectionLocations(BukkitAdapter.adapt(player)); + return new Pair<>(BukkitAdapter.adapt(locations[0]), BukkitAdapter.adapt(locations[1])); + } } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java index b4ef72b18..5e35d174a 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java @@ -1,6 +1,6 @@ package com.dfsek.terra.bukkit.listeners; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.transform.MapTransform; @@ -9,7 +9,7 @@ import com.dfsek.terra.api.util.FastRandom; import com.dfsek.terra.api.world.tree.Tree; import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.registry.config.TreeRegistry; +import com.dfsek.terra.config.pack.WorldConfig; import com.dfsek.terra.world.TerraWorld; import org.bukkit.Material; import org.bukkit.TreeType; @@ -47,14 +47,13 @@ public class CommonListener implements Listener { World bukkit = BukkitAdapter.adapt(e.getWorld()); if(!TerraWorld.isTerraWorld(bukkit)) return; TerraWorld tw = main.getWorld(bukkit); - ConfigPack c = tw.getConfig(); + WorldConfig c = tw.getConfig(); if(c.getTemplate().isDisableSaplings()) return; e.setCancelled(true); Block block = e.getLocation().getBlock(); BlockData data = block.getBlockData(); block.setType(Material.AIR); - TreeRegistry registry = c.getTreeRegistry(); - Tree tree = registry.get(TREE_TYPE_STRING_TRANSFORMER.translate(e.getSpecies())); + Tree tree = c.getTreeRegistry().get(TREE_TYPE_STRING_TRANSFORMER.translate(e.getSpecies())); org.bukkit.Location location = e.getLocation(); if(!tree.plant(new Location(bukkit, location.getX(), location.getY(), location.getZ()), new FastRandom())) block.setBlockData(data); } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/PaperListener.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/PaperListener.java index 01d298372..3945451f4 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/PaperListener.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/PaperListener.java @@ -1,7 +1,7 @@ package com.dfsek.terra.bukkit.listeners; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.async.AsyncStructureFinder; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.world.locate.AsyncStructureFinder; import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.population.items.TerraStructure; @@ -23,7 +23,7 @@ public class PaperListener implements Listener { String name = "minecraft:" + e.getType().getName(); main.getDebugLogger().info("Overriding structure location for \"" + name + "\""); TerraWorld tw = main.getWorld(BukkitAdapter.adapt(e.getWorld())); - TerraStructure config = tw.getConfig().getStructure(tw.getConfig().getTemplate().getLocatable().get(name)); + TerraStructure config = tw.getConfig().getStructureRegistry().get(tw.getConfig().getTemplate().getLocatable().get(name)); if(config != null) { AsyncStructureFinder finder = new AsyncStructureFinder(tw.getBiomeProvider(), config, BukkitAdapter.adapt(e.getOrigin()), 0, 500, location -> { if(location != null) @@ -32,7 +32,7 @@ public class PaperListener implements Listener { }, main); finder.run(); // Do this synchronously. } else { - main.getLogger().warning("No overrides are defined for \"" + name + "\""); + main.logger().warning("No overrides are defined for \"" + name + "\""); } } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/SpigotListener.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/SpigotListener.java index e3bfa8642..fe4681e61 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/SpigotListener.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/SpigotListener.java @@ -1,7 +1,7 @@ package com.dfsek.terra.bukkit.listeners; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.async.AsyncStructureFinder; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.world.locate.AsyncStructureFinder; import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.population.items.TerraStructure; @@ -37,7 +37,7 @@ public class SpigotListener implements Listener { if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return; TerraWorld tw = main.getWorld(BukkitAdapter.adapt(e.getEntity().getWorld())); EnderSignal signal = (EnderSignal) entity; - TerraStructure config = tw.getConfig().getStructure(tw.getConfig().getTemplate().getLocatable().get("STRONGHOLD")); + TerraStructure config = tw.getConfig().getStructureRegistry().get(tw.getConfig().getTemplate().getLocatable().get("STRONGHOLD")); if(config != null) { main.getDebugLogger().info("Overriding Ender Signal..."); AsyncStructureFinder finder = new AsyncStructureFinder(tw.getBiomeProvider(), config, BukkitAdapter.adapt(e.getLocation()), 0, 500, location -> { @@ -47,7 +47,7 @@ public class SpigotListener implements Listener { }, main); finder.run(); // Do this synchronously so eye doesn't change direction several ticks after spawning. } else - main.getLogger().warning("No overrides are defined for Strongholds. Ender Signals will not work correctly."); + main.logger().warning("No overrides are defined for Strongholds. Ender Signals will not work correctly."); } } @@ -56,9 +56,9 @@ public class SpigotListener implements Listener { if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return; if(!(e.getEntity() instanceof Villager)) return; if(((Villager) e.getEntity()).getProfession().equals(Villager.Profession.CARTOGRAPHER)) { - main.getLogger().severe("Prevented server crash by stopping Cartographer villager from spawning."); - main.getLogger().severe("Please upgrade to Paper, which has a StructureLocateEvent that fixes this issue"); - main.getLogger().severe("at the source, and doesn't require us to do stupid band-aids."); + main.logger().severe("Prevented server crash by stopping Cartographer villager from spawning."); + main.logger().severe("Please upgrade to Paper, which has a StructureLocateEvent that fixes this issue"); + main.logger().severe("at the source, and doesn't require us to do stupid band-aids."); e.setCancelled(true); // Cancel leveling if the villager is a Cartographer, to prevent crashing server. } } @@ -67,9 +67,9 @@ public class SpigotListener implements Listener { public void onCartographerLevel(VillagerCareerChangeEvent e) { if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return; if(e.getProfession().equals(Villager.Profession.CARTOGRAPHER)) { - main.getLogger().severe("Prevented server crash by stopping Cartographer villager from spawning."); - main.getLogger().severe("Please upgrade to Paper, which has a StructureLocateEvent that fixes this issue"); - main.getLogger().severe("at the source, and doesn't require us to do stupid band-aids."); + main.logger().severe("Prevented server crash by stopping Cartographer villager from spawning."); + main.logger().severe("Please upgrade to Paper, which has a StructureLocateEvent that fixes this issue"); + main.logger().severe("at the source, and doesn't require us to do stupid band-aids."); e.getEntity().setProfession(Villager.Profession.NITWIT); // Give villager new profession to prevent server crash. e.setCancelled(true); } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/TerraListener.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/TerraListener.java index 1549cefdb..78615d036 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/TerraListener.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/TerraListener.java @@ -1,10 +1,13 @@ package com.dfsek.terra.bukkit.listeners; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.api.core.event.EventListener; -import com.dfsek.terra.api.core.event.events.config.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.event.EventListener; +import com.dfsek.terra.api.event.annotations.Global; +import com.dfsek.terra.api.event.annotations.Priority; +import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent; import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.bukkit.world.BukkitTree; +import com.dfsek.terra.registry.exception.DuplicateEntryException; import org.bukkit.TreeType; public class TerraListener implements EventListener { @@ -14,9 +17,14 @@ public class TerraListener implements EventListener { this.main = main; } + @Global + @Priority(Priority.LOWEST) public void injectTrees(ConfigPackPreLoadEvent event) { for(TreeType value : TreeType.values()) { - event.getPack().getTreeRegistry().add(BukkitAdapter.TREE_TRANSFORMER.translate(value), new BukkitTree(value, main)); + try { + event.getPack().getTreeRegistry().add(BukkitAdapter.TREE_TRANSFORMER.translate(value), new BukkitTree(value, main)); + } catch(DuplicateEntryException ignore) { // If another addon has already registered trees, do nothing. + } } } } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/PopulationManager.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/PopulationManager.java index 99761067e..34ec49d68 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/PopulationManager.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/PopulationManager.java @@ -1,11 +1,12 @@ package com.dfsek.terra.bukkit.population; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.util.FastRandom; import com.dfsek.terra.api.util.GlueList; import com.dfsek.terra.api.world.generation.TerraBlockPopulator; +import com.dfsek.terra.bukkit.TerraBukkitPlugin; import com.dfsek.terra.profiler.ProfileFuture; import com.dfsek.terra.profiler.WorldProfiler; import org.jetbrains.annotations.NotNull; @@ -40,7 +41,7 @@ public class PopulationManager implements TerraBlockPopulator { needsPop.add(new ChunkCoordinate(chunk)); int x = chunk.getX(); int z = chunk.getZ(); - if(main.isEnabled()) { + if(((TerraBukkitPlugin) main).isEnabled()) { for(int xi = -1; xi <= 1; xi++) { for(int zi = -1; zi <= 1; zi++) { if(xi == 0 && zi == 0) continue; diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/SerializationUtil.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/SerializationUtil.java index 0a0267b6a..a297259c5 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/SerializationUtil.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/SerializationUtil.java @@ -41,7 +41,7 @@ public final class SerializationUtil { try { if(result.getName().contains(oldNameSpace)) { String newClassName = result.getName().replace(oldNameSpace, newNameSpace); - Class localClass = Class.forName(newClassName); + Class localClass = Class.forName(newClassName); Field nameField = ObjectStreamClass.class.getDeclaredField("name"); nameField.setAccessible(true); diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/structure/WorldEditUtil.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/structure/WorldEditUtil.java index e1a15dc4b..f7e5deb6c 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/structure/WorldEditUtil.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/structure/WorldEditUtil.java @@ -25,12 +25,10 @@ public final class WorldEditUtil { try { selection = we.getSession(sender).getSelection(BukkitAdapter.adapt(sender.getWorld())); } catch(IncompleteRegionException | ClassCastException e) { - sender.sendMessage("Invalid/incomplete selection!"); - return null; + throw new IllegalStateException("Invalid/incomplete selection!"); } if(selection == null) { - sender.sendMessage("Please make a selection before attempting to export!"); - return null; + throw new IllegalStateException("Please make a selection before attempting to export!"); } BlockVector3 min = selection.getMinimumPoint(); BlockVector3 max = selection.getMaximumPoint(); diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java index 737c56bdb..c50cd2711 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java @@ -6,22 +6,29 @@ import com.dfsek.terra.api.platform.CommandSender; import com.dfsek.terra.api.platform.block.Axis; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.BlockType; import com.dfsek.terra.api.platform.block.data.Bisected; import com.dfsek.terra.api.platform.block.data.Rail; import com.dfsek.terra.api.platform.block.data.RedstoneWire; import com.dfsek.terra.api.platform.block.data.Slab; import com.dfsek.terra.api.platform.block.data.Stairs; +import com.dfsek.terra.api.platform.inventory.ItemStack; import com.dfsek.terra.api.platform.inventory.item.Enchantment; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.transform.MapTransform; import com.dfsek.terra.api.transform.Transformer; import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.BukkitEntity; import com.dfsek.terra.bukkit.BukkitPlayer; +import com.dfsek.terra.bukkit.world.block.BukkitBlockTypeAndItem; import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData; +import com.dfsek.terra.bukkit.world.inventory.BukkitItemStack; import com.dfsek.terra.bukkit.world.inventory.meta.BukkitEnchantment; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.TreeType; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.util.Vector; @@ -346,6 +353,8 @@ public final class BukkitAdapter { } public static CommandSender adapt(org.bukkit.command.CommandSender sender) { + if(sender instanceof Player) return new BukkitPlayer((Player) sender); + if(sender instanceof Entity) return new BukkitEntity((Entity) sender); return new BukkitCommandSender(sender); } @@ -377,11 +386,27 @@ public final class BukkitAdapter { return ((BukkitEnchantment) enchantment).getHandle(); } - public static Player adapt(com.dfsek.terra.api.platform.Player player) { + public static Player adapt(com.dfsek.terra.api.platform.entity.Player player) { return ((BukkitPlayer) player).getHandle(); } - public static com.dfsek.terra.api.platform.Player adapt(Player player) { + public static com.dfsek.terra.api.platform.entity.Player adapt(Player player) { return new BukkitPlayer(player); } + + public static BukkitBlockTypeAndItem adapt(Material material) { + return new BukkitBlockTypeAndItem(material); + } + + public static Material adapt(BlockType type) { + return ((BukkitBlockTypeAndItem) type).getHandle(); + } + + public static ItemStack adapt(org.bukkit.inventory.ItemStack in) { + return new BukkitItemStack(in); + } + + public static org.bukkit.inventory.ItemStack adapt(ItemStack in) { + return ((BukkitItemStack) in).getHandle(); + } } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitTree.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitTree.java index db12c9c18..d4364a1b0 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitTree.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitTree.java @@ -1,15 +1,13 @@ package com.dfsek.terra.bukkit.world; -import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.MaterialData; import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.world.tree.Tree; -import com.dfsek.terra.util.MaterialSet; import org.bukkit.TreeType; import java.util.Random; -import java.util.Set; public class BukkitTree implements Tree { private final TreeType delegate; @@ -26,18 +24,18 @@ public class BukkitTree implements Tree { WorldHandle handle = main.getWorldHandle(); switch(type) { case CRIMSON_FUNGUS: - return MaterialSet.get(handle.createMaterialData("minecraft:crimson_nylium")); + return MaterialSet.get(handle.createBlockData("minecraft:crimson_nylium")); case WARPED_FUNGUS: - return MaterialSet.get(handle.createMaterialData("minecraft:warped_nylium")); + return MaterialSet.get(handle.createBlockData("minecraft:warped_nylium")); case BROWN_MUSHROOM: case RED_MUSHROOM: - return MaterialSet.get(handle.createMaterialData("minecraft:mycelium"), handle.createMaterialData("minecraft:grass_block"), - handle.createMaterialData("minecraft:podzol")); + return MaterialSet.get(handle.createBlockData("minecraft:mycelium"), handle.createBlockData("minecraft:grass_block"), + handle.createBlockData("minecraft:podzol")); case CHORUS_PLANT: - return MaterialSet.get(handle.createMaterialData("minecraft:end_stone")); + return MaterialSet.get(handle.createBlockData("minecraft:end_stone")); default: - return MaterialSet.get(handle.createMaterialData("minecraft:grass_block"), handle.createMaterialData("minecraft:dirt"), - handle.createMaterialData("minecraft:podzol")); + return MaterialSet.get(handle.createBlockData("minecraft:grass_block"), handle.createBlockData("minecraft:dirt"), + handle.createBlockData("minecraft:podzol")); } } @@ -47,7 +45,7 @@ public class BukkitTree implements Tree { } @Override - public Set getSpawnable() { + public MaterialSet getSpawnable() { return spawnable; } } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorld.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorld.java index 720315bca..294314cbf 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorld.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorld.java @@ -68,13 +68,13 @@ public class BukkitWorld implements World { } @Override - public Block getBlockAt(Location l) { - return new BukkitBlock(delegate.getBlockAt(l.getBlockX(), l.getBlockY(), l.getBlockZ())); + public Entity spawnEntity(Location location, EntityType entityType) { + return new BukkitEntity(delegate.spawnEntity(BukkitAdapter.adapt(location), ((BukkitEntityType) entityType).getHandle())); } @Override - public Entity spawnEntity(Location location, EntityType entityType) { - return new BukkitEntity(delegate.spawnEntity(BukkitAdapter.adapt(location), ((BukkitEntityType) entityType).getHandle())); + public int getMinHeight() { + return 0; } @Override diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlock.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlock.java index aaa5a9b47..dcf49acdd 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlock.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlock.java @@ -4,7 +4,7 @@ import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.block.BlockType; import com.dfsek.terra.api.platform.block.state.BlockState; import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData; @@ -53,8 +53,8 @@ public class BukkitBlock implements Block { } @Override - public MaterialData getType() { - return new BukkitMaterialData(delegate.getType()); + public BlockType getType() { + return BukkitAdapter.adapt(delegate.getType()); } @Override diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlockTypeAndItem.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlockTypeAndItem.java new file mode 100644 index 000000000..aeafa9823 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlockTypeAndItem.java @@ -0,0 +1,52 @@ +package com.dfsek.terra.bukkit.world.block; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockType; +import com.dfsek.terra.api.platform.inventory.Item; +import com.dfsek.terra.api.platform.inventory.ItemStack; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import org.bukkit.Material; + +public class BukkitBlockTypeAndItem implements BlockType, Item { + private final Material delegate; + + public BukkitBlockTypeAndItem(Material delegate) { + this.delegate = delegate; + } + + @Override + public Material getHandle() { + return delegate; + } + + @Override + public BlockData getDefaultData() { + return BukkitAdapter.adapt(delegate.createBlockData()); + } + + @Override + public boolean isSolid() { + return delegate.isSolid(); + } + + @Override + public ItemStack newItemStack(int amount) { + return BukkitAdapter.adapt(new org.bukkit.inventory.ItemStack(delegate, amount)); + } + + @Override + public double getMaxDurability() { + return delegate.getMaxDurability(); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof BukkitBlockTypeAndItem)) return false; + return delegate == ((BukkitBlockTypeAndItem) obj).delegate; + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitMaterialData.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitMaterialData.java deleted file mode 100644 index e0bfba568..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitMaterialData.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.dfsek.terra.bukkit.world.block; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; -import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData; -import org.bukkit.Material; - -public class BukkitMaterialData implements MaterialData { - private final Material delegate; - - public BukkitMaterialData(Material delegate) { - this.delegate = delegate; - } - - @Override - public boolean matches(MaterialData other) { - return ((BukkitMaterialData) other).getHandle().equals(delegate); - } - - @Override - public boolean matches(BlockData other) { - return ((BukkitMaterialData) other.getMaterial()).getHandle().equals(delegate); - } - - @Override - public boolean isSolid() { - return delegate.isSolid(); - } - - @Override - public boolean isAir() { - return delegate.isAir(); - } - - @Override - public double getMaxDurability() { - return delegate.getMaxDurability(); - } - - @Override - public BlockData createBlockData() { - return BukkitBlockData.newInstance(delegate.createBlockData()); - } - - @Override - public Material getHandle() { - return delegate; - } - - @Override - public int hashCode() { - return delegate.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if(!(obj instanceof BukkitMaterialData)) return false; - BukkitMaterialData other = (BukkitMaterialData) obj; - - return other.getHandle().equals(this.delegate); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockData.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockData.java index dc3295f73..e0dffe72b 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockData.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockData.java @@ -1,9 +1,10 @@ package com.dfsek.terra.bukkit.world.block.data; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.block.BlockType; import com.dfsek.terra.bukkit.TerraBukkitPlugin; -import com.dfsek.terra.bukkit.world.block.BukkitMaterialData; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import org.bukkit.Material; import org.bukkit.block.data.AnaloguePowerable; import org.bukkit.block.data.Directional; import org.bukkit.block.data.MultipleFacing; @@ -28,7 +29,7 @@ public class BukkitBlockData implements BlockData { if(bukkitData instanceof Rail) return new BukkitRail((Rail) bukkitData); if(bukkitData instanceof Stairs) return new BukkitStairs((Stairs) bukkitData); if(bukkitData instanceof Slab) return new BukkitSlab((Slab) bukkitData); - if(TerraBukkitPlugin.BUKKIT_VERSION.above(TerraBukkitPlugin.Version.V1_16) && bukkitData instanceof Wall) { // Wall only exists on 1.16 and up. + if(TerraBukkitPlugin.BUKKIT_VERSION.above(TerraBukkitPlugin.BukkitVersion.V1_16) && bukkitData instanceof Wall) { // Wall only exists on 1.16 and up. return new BukkitWall((Wall) bukkitData); } @@ -52,13 +53,13 @@ public class BukkitBlockData implements BlockData { } @Override - public MaterialData getMaterial() { - return new BukkitMaterialData(delegate.getMaterial()); + public BlockType getBlockType() { + return BukkitAdapter.adapt(delegate.getMaterial()); } @Override - public boolean matches(MaterialData materialData) { - return delegate.getMaterial().equals(((BukkitMaterialData) materialData).getHandle()); + public boolean matches(BlockData data) { + return delegate.getMaterial() == ((BukkitBlockData) data).getHandle().getMaterial(); } @Override @@ -76,4 +77,14 @@ public class BukkitBlockData implements BlockData { public String getAsString() { return delegate.getAsString(false); } + + @Override + public boolean isAir() { + return delegate.getMaterial().isAir(); + } + + @Override + public boolean isStructureVoid() { + return delegate.getMaterial() == Material.STRUCTURE_VOID; + } } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitContainer.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitContainer.java index c95040f8c..cdb1fe636 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitContainer.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitContainer.java @@ -15,4 +15,8 @@ public class BukkitContainer extends BukkitBlockState implements Container { return new BukkitInventory(((org.bukkit.block.Container) getHandle()).getInventory()); } + @Override + public boolean update(boolean applyPhysics) { + return false; // This clears the inventory. we don't want that. + } } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitSign.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitSign.java index 6b90ec18f..fe19fac78 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitSign.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitSign.java @@ -24,12 +24,11 @@ public class BukkitSign extends BukkitBlockState implements Sign { ((org.bukkit.block.Sign) getHandle()).setLine(index, line); } - @Override public void applyState(String state) { SerialState.parse(state).forEach((k, v) -> { - if(!v.startsWith("text")) throw new IllegalArgumentException("Invalid property: " + k); - setLine(Integer.parseInt(k) + 1, v.substring(4)); + if(!k.startsWith("text")) throw new IllegalArgumentException("Invalid property: " + k); + setLine(Integer.parseInt(k.substring(4)), v); }); } } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemStack.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemStack.java index 5d94c45c5..b42f7319d 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemStack.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemStack.java @@ -1,12 +1,12 @@ package com.dfsek.terra.bukkit.world.inventory; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.inventory.Item; import com.dfsek.terra.api.platform.inventory.ItemStack; import com.dfsek.terra.api.platform.inventory.item.ItemMeta; -import com.dfsek.terra.bukkit.world.block.BukkitMaterialData; +import com.dfsek.terra.bukkit.world.BukkitAdapter; public class BukkitItemStack implements ItemStack { - private org.bukkit.inventory.ItemStack delegate; + private final org.bukkit.inventory.ItemStack delegate; public BukkitItemStack(org.bukkit.inventory.ItemStack delegate) { this.delegate = delegate; @@ -23,20 +23,8 @@ public class BukkitItemStack implements ItemStack { } @Override - public MaterialData getType() { - return new BukkitMaterialData(delegate.getType()); - } - - @Override - public ItemStack clone() { - BukkitItemStack clone; - try { - clone = (BukkitItemStack) super.clone(); - clone.delegate = delegate.clone(); - } catch(CloneNotSupportedException e) { - throw new Error(e); - } - return clone; + public Item getType() { + return BukkitAdapter.adapt(delegate.getType()); } @Override diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index 78d279159..2e085d24d 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -1,56 +1,49 @@ import com.dfsek.terra.configureCommon +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import net.fabricmc.loom.LoomGradleExtension import net.fabricmc.loom.task.RemapJarTask -buildscript { - repositories { - mavenCentral() - maven { - name = "Fabric" - url = uri("https://maven.fabricmc.net/") - } - } -// dependencies { -// classpath("net.fabricmc:fabric-loom:+") -// } -} - plugins { - id("fabric-loom").version("0.5.9") `java-library` + id("fabric-loom").version("0.6-SNAPSHOT") } -//apply(plugin = "fabric-loom") configureCommon() +tasks.named("shadowJar") { + relocate("org.json", "com.dfsek.terra.lib.json") + relocate("org.yaml", "com.dfsek.terra.lib.yaml") +} + group = "com.dfsek.terra.fabric" +dependencies { + "shadedApi"(project(":common")) + "shadedImplementation"("org.yaml:snakeyaml:1.27") + "shadedImplementation"("com.googlecode.json-simple:json-simple:1.1.1") + + "minecraft"("com.mojang:minecraft:1.16.5") + "mappings"("net.fabricmc:yarn:1.16.5+build.5:v2") + "modImplementation"("net.fabricmc:fabric-loader:0.11.2") + + "modImplementation"("net.fabricmc.fabric-api:fabric-api:0.31.0+1.16") +} + +tasks.named("shadowJar") { + relocate("org.json", "com.dfsek.terra.lib.json") + relocate("org.yaml", "com.dfsek.terra.lib.yaml") +} + configure { accessWidener("src/main/resources/terra.accesswidener") } tasks.register("remapShadedJar") { - setProperty("input", file("build/libs/fabric-${version}-shaded.jar")) - setProperty("addNestedDependencies", false) - setProperty("remapAccessWidener", true) + val shadowJar = tasks.getByName("shadowJar") + dependsOn(shadowJar) + input.set(shadowJar.archiveFile) + archiveFileName.set(shadowJar.archiveFileName.get().replace(Regex("-shaded\\.jar$"), "-shaded-mapped.jar")) + addNestedDependencies.set(true) + remapAccessWidener.set(true) } - -dependencies { - "shadedApi"(project(":common")) - "shadedImplementation"("org.yaml:snakeyaml:1.27") - "shadedImplementation"("com.googlecode.json-simple:json-simple:1.1.1") - - - // To change the versions see the gradle.properties file - "minecraft"("com.mojang:minecraft:1.16.4") - "mappings"("net.fabricmc:yarn:1.16.4+build.6:v2") - "modImplementation"("net.fabricmc:fabric-loader:0.10.6+build.214") - - // Fabric API. This is technically optional, but you probably want it anyway. - "modImplementation"("net.fabricmc.fabric-api:fabric-api:0.25.1+build.416-1.16") - - "compileOnly"("net.fabricmc:sponge-mixin:+") - "annotationProcessor"("net.fabricmc:sponge-mixin:+") - "annotationProcessor"("net.fabricmc:fabric-loom:+") -} \ No newline at end of file diff --git a/platforms/fabric/gradle.properties b/platforms/fabric/gradle.properties new file mode 100644 index 000000000..95b4763a8 --- /dev/null +++ b/platforms/fabric/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx4G diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java index 822902e40..d34893776 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java @@ -1,38 +1,64 @@ package com.dfsek.terra.fabric; import com.dfsek.tectonic.loading.TypeRegistry; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.api.core.event.EventManager; -import com.dfsek.terra.api.core.event.TerraEventManager; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.addons.TerraAddon; +import com.dfsek.terra.api.addons.annotations.Addon; +import com.dfsek.terra.api.addons.annotations.Author; +import com.dfsek.terra.api.addons.annotations.Version; +import com.dfsek.terra.api.command.CommandManager; +import com.dfsek.terra.api.command.TerraCommandManager; +import com.dfsek.terra.api.command.exception.CommandException; +import com.dfsek.terra.api.command.exception.MalformedCommandException; +import com.dfsek.terra.api.event.EventListener; +import com.dfsek.terra.api.event.EventManager; +import com.dfsek.terra.api.event.TerraEventManager; +import com.dfsek.terra.api.event.annotations.Global; +import com.dfsek.terra.api.event.annotations.Priority; +import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.platform.CommandSender; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; import com.dfsek.terra.api.platform.handle.ItemHandle; import com.dfsek.terra.api.platform.handle.WorldHandle; import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.transform.MapTransform; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.registry.LockedRegistry; import com.dfsek.terra.api.transform.NotNullValidator; import com.dfsek.terra.api.transform.Transformer; -import com.dfsek.terra.biome.TerraBiome; +import com.dfsek.terra.api.util.logging.DebugLogger; +import com.dfsek.terra.api.util.logging.Logger; +import com.dfsek.terra.api.world.tree.Tree; +import com.dfsek.terra.commands.CommandUtil; import com.dfsek.terra.config.GenericLoaders; import com.dfsek.terra.config.PluginConfig; +import com.dfsek.terra.config.builder.BiomeBuilder; import com.dfsek.terra.config.lang.LangUtil; import com.dfsek.terra.config.lang.Language; import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.debug.DebugLogger; import com.dfsek.terra.fabric.inventory.FabricItemHandle; import com.dfsek.terra.fabric.mixin.GeneratorTypeAccessor; +import com.dfsek.terra.fabric.world.FabricAdapter; import com.dfsek.terra.fabric.world.FabricBiome; +import com.dfsek.terra.fabric.world.FabricTree; import com.dfsek.terra.fabric.world.FabricWorldHandle; import com.dfsek.terra.fabric.world.TerraBiomeSource; import com.dfsek.terra.fabric.world.features.PopulatorFeature; +import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator; import com.dfsek.terra.fabric.world.generator.FabricChunkGeneratorWrapper; -import com.dfsek.terra.registry.ConfigRegistry; +import com.dfsek.terra.registry.exception.DuplicateEntryException; +import com.dfsek.terra.registry.master.AddonRegistry; +import com.dfsek.terra.registry.master.ConfigRegistry; import com.dfsek.terra.world.TerraWorld; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; import net.fabricmc.api.EnvType; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.block.Blocks; import net.minecraft.client.world.GeneratorType; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.Registry; @@ -54,117 +80,132 @@ import net.minecraft.world.gen.feature.FeatureConfig; import net.minecraft.world.gen.surfacebuilder.SurfaceBuilder; import net.minecraft.world.gen.surfacebuilder.TernarySurfaceConfig; import org.apache.commons.io.FileUtils; +import org.apache.logging.log4j.LogManager; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; +import java.util.Locale; import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; + +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + public class TerraFabricPlugin implements TerraPlugin, ModInitializer { - private final Map worldMap = new HashMap<>(); + public static final PopulatorFeature POPULATOR_FEATURE = new PopulatorFeature(DefaultFeatureConfig.CODEC); + public static final ConfiguredFeature POPULATOR_CONFIGURED_FEATURE = POPULATOR_FEATURE.configure(FeatureConfig.DEFAULT).decorate(Decorator.NOPE.configure(NopeDecoratorConfig.INSTANCE)); private static TerraFabricPlugin instance; - + private final Map worldMap = new HashMap<>(); private final EventManager eventManager = new TerraEventManager(this); + private final GenericLoaders genericLoaders = new GenericLoaders(this); + private final Logger logger = new Logger() { + private final org.apache.logging.log4j.Logger logger = LogManager.getLogger(); + + @Override + public void info(String message) { + logger.info(message); + } + + @Override + public void warning(String message) { + logger.warn(message); + } + + @Override + public void severe(String message) { + logger.error(message); + } + }; + private final DebugLogger debugLogger = new DebugLogger(logger); + private final ItemHandle itemHandle = new FabricItemHandle(); + private final WorldHandle worldHandle = new FabricWorldHandle(); + private final ConfigRegistry registry = new ConfigRegistry(); + private final CheckedRegistry checkedRegistry = new CheckedRegistry<>(registry); + private final AddonRegistry addonRegistry = new AddonRegistry(new FabricAddon(this), this); + private final LockedRegistry addonLockedRegistry = new LockedRegistry<>(addonRegistry); + private final PluginConfig config = new PluginConfig(); + private final Transformer biomeFixer = new Transformer.Builder() + .addTransform(id -> BuiltinRegistries.BIOME.get(Identifier.tryParse(id)), new NotNullValidator<>()) + .addTransform(id -> BuiltinRegistries.BIOME.get(Identifier.tryParse("minecraft:" + id.toLowerCase())), new NotNullValidator<>()).build(); + private File dataFolder; public static TerraFabricPlugin getInstance() { return instance; } - public static final PopulatorFeature POPULATOR_FEATURE = new PopulatorFeature(DefaultFeatureConfig.CODEC); - public static final ConfiguredFeature POPULATOR_CONFIGURED_FEATURE = POPULATOR_FEATURE.configure(FeatureConfig.DEFAULT).decorate(Decorator.NOPE.configure(NopeDecoratorConfig.INSTANCE)); - - private final GenericLoaders genericLoaders = new GenericLoaders(this); - private final Logger logger = Logger.getLogger("Terra"); - private final DebugLogger debugLogger = new DebugLogger(logger); - private final ItemHandle itemHandle = new FabricItemHandle(); - private final WorldHandle worldHandle = new FabricWorldHandle(); - private final ConfigRegistry registry = new ConfigRegistry(); - private File config; - private static final Transformer> TREE_TRANSFORMER = new Transformer.Builder>() - .addTransform(TerraFabricPlugin::getFeature) - .addTransform(new MapTransform>() - .add("BROWN_MUSHROOM", ConfiguredFeatures.BROWN_MUSHROOM_GIANT) - .add("RED_MUSHROOM", ConfiguredFeatures.RED_MUSHROOM_GIANT) - .add("JUNGLE", ConfiguredFeatures.MEGA_JUNGLE_TREE) - .add("JUNGLE_COCOA", ConfiguredFeatures.JUNGLE_TREE) - .add("LARGE_OAK", ConfiguredFeatures.FANCY_OAK) - .add("LARGE_SPRUCE", ConfiguredFeatures.PINE) - .add("SMALL_JUNGLE", ConfiguredFeatures.JUNGLE_TREE) - .add("SWAMP_OAK", ConfiguredFeatures.SWAMP_TREE) - .add("TALL_BIRCH", ConfiguredFeatures.BIRCH_TALL) - .add("ACACIA", ConfiguredFeatures.ACACIA) - .add("BIRCH", ConfiguredFeatures.BIRCH) - .add("DARK_OAK", ConfiguredFeatures.DARK_OAK) - .add("OAK", ConfiguredFeatures.OAK) - .add("CHORUS_PLANT", ConfiguredFeatures.CHORUS_PLANT) - .add("SPRUCE", ConfiguredFeatures.SPRUCE) - .add("JUNGLE_BUSH", ConfiguredFeatures.JUNGLE_BUSH) - .add("MEGA_SPRUCE", ConfiguredFeatures.MEGA_SPRUCE) - .add("CRIMSON_FUNGUS", ConfiguredFeatures.CRIMSON_FUNGI) - .add("WARPED_FUNGUS", ConfiguredFeatures.WARPED_FUNGI)).build(); - private final PluginConfig plugin = new PluginConfig(); + public static String createBiomeID(ConfigPack pack, String biomeID) { + return pack.getTemplate().getID().toLowerCase() + "/" + biomeID.toLowerCase(Locale.ROOT); + } @Override public WorldHandle getWorldHandle() { return worldHandle; } - @Override - public boolean isEnabled() { - return false; - } - @Override public TerraWorld getWorld(World world) { + if(worldMap.size() > 1) System.out.println(worldMap.size()); return worldMap.computeIfAbsent(world.getSeed(), w -> { logger.info("Loading world " + w); - return new TerraWorld(world, getRegistry().get("DEFAULT"), this); + return new TerraWorld(world, ((FabricChunkGeneratorWrapper) ((FabricChunkGenerator) world.getGenerator()).getHandle()).getPack(), this); }); } @Override - public Logger getLogger() { + public Logger logger() { return logger; } @Override public PluginConfig getTerraConfig() { - return plugin; - } - - @Override - public File getDataFolder() { return config; } + @Override + public File getDataFolder() { + return dataFolder; + } + @Override public boolean isDebug() { - return false; + return true; } @Override public Language getLanguage() { - try { - return new Language(new File(getDataFolder(), "lang/en_us.yml")); - } catch(IOException e) { - throw new IllegalArgumentException(); - } + return LangUtil.getLanguage(); } @Override - public ConfigRegistry getRegistry() { - return registry; + public CheckedRegistry getConfigRegistry() { + return checkedRegistry; } @Override - public void reload() { + public LockedRegistry getAddons() { + return addonLockedRegistry; + } + @Override + public boolean reload() { + config.load(this); + LangUtil.load(config.getLanguage(), this); // Load language. + boolean succeed = registry.loadAll(this); + Map newMap = new HashMap<>(); + worldMap.forEach((seed, tw) -> { + tw.getConfig().getSamplerCache().clear(); + String packID = tw.getConfig().getTemplate().getID(); + newMap.put(seed, new TerraWorld(tw.getWorld(), registry.get(packID), this)); + }); + worldMap.clear(); + worldMap.putAll(newMap); + return succeed; } @Override @@ -192,24 +233,15 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { return debugLogger; } - Transformer biomeFixer = new Transformer.Builder() - .addTransform(id -> BuiltinRegistries.BIOME.get(Identifier.tryParse(id)), new NotNullValidator<>()) - .addTransform(id -> BuiltinRegistries.BIOME.get(Identifier.tryParse("minecraft:" + id.toLowerCase())), new NotNullValidator<>()).build(); - @Override public void register(TypeRegistry registry) { genericLoaders.register(registry); registry .registerLoader(BlockData.class, (t, o, l) -> worldHandle.createBlockData((String) o)) - .registerLoader(MaterialData.class, (t, o, l) -> worldHandle.createMaterialData((String) o)) .registerLoader(com.dfsek.terra.api.platform.world.Biome.class, (t, o, l) -> new FabricBiome(biomeFixer.translate((String) o))); } - public static String createBiomeID(ConfigPack pack, TerraBiome biome) { - return pack.getTemplate().getID().toLowerCase() + "/" + biome.getID().toLowerCase(); - } - - private Biome createBiome(TerraBiome biome) { + private Biome createBiome(BiomeBuilder biome) { SpawnSettings.Builder spawnSettings = new SpawnSettings.Builder(); DefaultBiomeFeatures.addFarmAnimals(spawnSettings); DefaultBiomeFeatures.addMonsters(spawnSettings, 95, 5, 100); @@ -220,18 +252,15 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { generationSettings.surfaceBuilder(SurfaceBuilder.DEFAULT.withConfig(new TernarySurfaceConfig(Blocks.GRASS_BLOCK.getDefaultState(), Blocks.DIRT.getDefaultState(), Blocks.GRAVEL.getDefaultState()))); // It needs a surfacebuilder, even though we dont use it. generationSettings.feature(GenerationStep.Feature.VEGETAL_DECORATION, POPULATOR_CONFIGURED_FEATURE); + BiomeEffects.Builder effects = new BiomeEffects.Builder() - .waterColor(vanilla.getWaterColor()) - .waterFogColor(vanilla.getWaterFogColor()) - .fogColor(vanilla.getFogColor()) - .skyColor(vanilla.getSkyColor()) - .grassColorModifier(vanilla.getEffects().getGrassColorModifier()); - if(vanilla.getEffects().getGrassColor().isPresent()) { - effects.grassColor(vanilla.getEffects().getGrassColor().get()); - } - if(vanilla.getEffects().getFoliageColor().isPresent()) { - effects.foliageColor(vanilla.getEffects().getFoliageColor().get()); - } + .waterColor(vanilla.getEffects().waterColor) + .waterFogColor(vanilla.getEffects().waterFogColor) + .fogColor(vanilla.getEffects().fogColor) + .skyColor(vanilla.getEffects().skyColor) + .grassColorModifier(vanilla.getEffects().grassColorModifier); + vanilla.getEffects().grassColor.ifPresent(effects::grassColor); + vanilla.getEffects().foliageColor.ifPresent(effects::foliageColor); return (new Biome.Builder()) .precipitation(vanilla.getPrecipitation()) @@ -246,52 +275,157 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { .build(); } - private static ConfiguredFeature getFeature(String name) { - Class featuresClass = ConfiguredFeatures.class; - Field feature; - try { - feature = featuresClass.getField(name); - return (ConfiguredFeature) feature.get(null); - } catch(NoSuchFieldException | IllegalAccessException e) { - throw new IllegalArgumentException("No such feature: " + name); - } - } - + @SuppressWarnings("unchecked") @Override public void onInitialize() { - logger.setLevel(Level.INFO); instance = this; - config = new File(FabricLoader.getInstance().getConfigDir().toFile(), "Terra"); + this.dataFolder = new File(FabricLoader.getInstance().getConfigDir().toFile(), "Terra"); saveDefaultConfig(); - plugin.load(this); - LangUtil.load("en_us", this); + config.load(this); + LangUtil.load(config.getLanguage(), this); logger.info("Initializing Terra..."); + if(!addonRegistry.loadAll()) { + throw new IllegalStateException("Failed to load addons. Please correct addon installations to continue."); + } + logger.info("Loaded addons."); + registry.loadAll(this); + logger.info("Loaded packs."); + Registry.register(Registry.FEATURE, new Identifier("terra", "flora_populator"), POPULATOR_FEATURE); RegistryKey> floraKey = RegistryKey.of(Registry.CONFIGURED_FEATURE_WORLDGEN, new Identifier("terra", "flora_populator")); Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, floraKey.getValue(), POPULATOR_CONFIGURED_FEATURE); - registry.forEach(pack -> pack.getBiomeRegistry().forEach(biome -> Registry.register(BuiltinRegistries.BIOME, new Identifier("terra", createBiomeID(pack, biome)), createBiome(biome)))); // Register all Terra biomes. + registry.forEach(pack -> pack.getBiomeRegistry().forEach((id, biome) -> Registry.register(BuiltinRegistries.BIOME, new Identifier("terra", createBiomeID(pack, id)), createBiome(biome)))); // Register all Terra biomes. Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), FabricChunkGeneratorWrapper.CODEC); Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), TerraBiomeSource.CODEC); - if(FabricLoader.getInstance().getEnvironmentType().equals(EnvType.CLIENT)) { - GeneratorTypeAccessor.getValues().add(new GeneratorType("terra") { - @Override - protected ChunkGenerator getChunkGenerator(Registry biomeRegistry, Registry chunkGeneratorSettingsRegistry, long seed) { - ConfigPack pack = registry.get("DEFAULT"); - return new FabricChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, seed, pack), seed, pack); - } + if(FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { + registry.forEach(pack -> { + final GeneratorType generatorType = new GeneratorType("terra." + pack.getTemplate().getID()) { + @Override + protected ChunkGenerator getChunkGenerator(Registry biomeRegistry, Registry chunkGeneratorSettingsRegistry, long seed) { + return new FabricChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, seed, pack), seed, pack); + } + }; + //noinspection ConstantConditions + ((GeneratorTypeAccessor) generatorType).setTranslationKey(new LiteralText("Terra:" + pack.getTemplate().getID())); + GeneratorTypeAccessor.getVALUES().add(generatorType); }); } + CommandManager manager = new TerraCommandManager(this); + try { + CommandUtil.registerAll(manager); + } catch(MalformedCommandException e) { + e.printStackTrace(); // TODO do something here even though this should literally never happen + } + + + CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> { + int max = manager.getMaxArgumentDepth(); + System.out.println("MAX:" + max); + RequiredArgumentBuilder arg = argument("arg" + (max - 1), StringArgumentType.word()); + for(int i = 0; i < max; i++) { + System.out.println("arg " + i); + RequiredArgumentBuilder next = argument("arg" + (max - i - 1), StringArgumentType.word()); + + arg = next.then(assemble(arg, manager)); + } + + dispatcher.register(literal("terra").executes(context -> 1).then(assemble(arg, manager))); + dispatcher.register(literal("te").executes(context -> 1).then(assemble(arg, manager))); + //dispatcher.register(literal("te").redirect(root)); + } + ); + } + private RequiredArgumentBuilder assemble(RequiredArgumentBuilder in, CommandManager manager) { + return in.suggests((context, builder) -> { + List args = parseCommand(context.getInput()); + CommandSender sender = FabricAdapter.adapt(context.getSource()); + try { + manager.tabComplete(args.remove(0), sender, args).forEach(builder::suggest); + } catch(CommandException e) { + sender.sendMessage(e.getMessage()); + } + return builder.buildFuture(); + }).executes(context -> { + List args = parseCommand(context.getInput()); + try { + manager.execute(args.remove(0), FabricAdapter.adapt(context.getSource()), args); + } catch(CommandException e) { + context.getSource().sendError(new LiteralText(e.getMessage())); + } + return 1; + }); + } + + private List parseCommand(String command) { + if(command.startsWith("/terra ")) command = command.substring("/terra ".length()); + else if(command.startsWith("/te ")) command = command.substring("/te ".length()); + List c = new ArrayList<>(Arrays.asList(command.split(" "))); + if(command.endsWith(" ")) c.add(""); + return c; + } + + @Override public EventManager getEventManager() { return eventManager; } + + @Addon("Terra-Fabric") + @Author("Terra") + @Version("1.0.0") + private static final class FabricAddon extends TerraAddon implements EventListener { + + private final TerraPlugin main; + + private FabricAddon(TerraPlugin main) { + this.main = main; + } + + @Override + public void initialize() { + main.getEventManager().registerListener(this, this); + } + + @Priority(Priority.LOWEST) + @Global + public void injectTrees(ConfigPackPreLoadEvent event) { + CheckedRegistry treeRegistry = event.getPack().getTreeRegistry(); + injectTree(treeRegistry, "BROWN_MUSHROOM", ConfiguredFeatures.HUGE_BROWN_MUSHROOM); + injectTree(treeRegistry, "RED_MUSHROOM", ConfiguredFeatures.HUGE_RED_MUSHROOM); + injectTree(treeRegistry, "JUNGLE", ConfiguredFeatures.MEGA_JUNGLE_TREE); + injectTree(treeRegistry, "JUNGLE_COCOA", ConfiguredFeatures.JUNGLE_TREE); + injectTree(treeRegistry, "LARGE_OAK", ConfiguredFeatures.FANCY_OAK); + injectTree(treeRegistry, "LARGE_SPRUCE", ConfiguredFeatures.PINE); + injectTree(treeRegistry, "SMALL_JUNGLE", ConfiguredFeatures.JUNGLE_TREE); + injectTree(treeRegistry, "SWAMP_OAK", ConfiguredFeatures.SWAMP_TREE); + injectTree(treeRegistry, "TALL_BIRCH", ConfiguredFeatures.BIRCH_TALL); + injectTree(treeRegistry, "ACACIA", ConfiguredFeatures.ACACIA); + injectTree(treeRegistry, "BIRCH", ConfiguredFeatures.BIRCH); + injectTree(treeRegistry, "DARK_OAK", ConfiguredFeatures.DARK_OAK); + injectTree(treeRegistry, "OAK", ConfiguredFeatures.OAK); + injectTree(treeRegistry, "CHORUS_PLANT", ConfiguredFeatures.CHORUS_PLANT); + injectTree(treeRegistry, "SPRUCE", ConfiguredFeatures.SPRUCE); + injectTree(treeRegistry, "JUNGLE_BUSH", ConfiguredFeatures.JUNGLE_BUSH); + injectTree(treeRegistry, "MEGA_SPRUCE", ConfiguredFeatures.MEGA_SPRUCE); + injectTree(treeRegistry, "CRIMSON_FUNGUS", ConfiguredFeatures.CRIMSON_FUNGI); + injectTree(treeRegistry, "WARPED_FUNGUS", ConfiguredFeatures.WARPED_FUNGI); + } + + + private void injectTree(CheckedRegistry registry, String id, ConfiguredFeature tree) { + try { + registry.add(id, new FabricTree(tree)); + } catch(DuplicateEntryException ignore) { + } + } + } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/command/FabricCommandAdapter.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/command/FabricCommandAdapter.java new file mode 100644 index 000000000..a8db1bb54 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/command/FabricCommandAdapter.java @@ -0,0 +1,7 @@ +package com.dfsek.terra.fabric.command; + +public class FabricCommandAdapter { + public static void register() { + + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/command/StringListArgumentType.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/command/StringListArgumentType.java new file mode 100644 index 000000000..392aaf1af --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/command/StringListArgumentType.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.fabric.command; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class StringListArgumentType implements ArgumentType> { + @Override + public List parse(StringReader reader) { + final String text = reader.getRemaining(); + reader.setCursor(reader.getTotalLength()); + return new ArrayList<>(Arrays.asList(text.split(" "))); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricEnchantment.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricEnchantment.java new file mode 100644 index 000000000..347f53315 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricEnchantment.java @@ -0,0 +1,41 @@ +package com.dfsek.terra.fabric.inventory; + +import com.dfsek.terra.api.platform.inventory.ItemStack; +import com.dfsek.terra.api.platform.inventory.item.Enchantment; +import com.dfsek.terra.fabric.world.FabricAdapter; +import net.minecraft.util.registry.Registry; + +import java.util.Objects; + +public class FabricEnchantment implements Enchantment { + private final net.minecraft.enchantment.Enchantment enchantment; + + public FabricEnchantment(net.minecraft.enchantment.Enchantment enchantment) { + this.enchantment = enchantment; + } + + @Override + public net.minecraft.enchantment.Enchantment getHandle() { + return enchantment; + } + + @Override + public boolean canEnchantItem(ItemStack itemStack) { + return enchantment.isAcceptableItem(FabricAdapter.adapt(itemStack)); + } + + @Override + public String getID() { + return Objects.requireNonNull(Registry.ENCHANTMENT.getId(enchantment)).toString(); + } + + @Override + public boolean conflictsWith(Enchantment other) { + return !enchantment.canCombine(FabricAdapter.adapt(other)); + } + + @Override + public int getMaxLevel() { + return enchantment.getMaxLevel(); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricInventory.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricInventory.java new file mode 100644 index 000000000..8b86f657d --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricInventory.java @@ -0,0 +1,35 @@ +package com.dfsek.terra.fabric.inventory; + +import com.dfsek.terra.api.platform.inventory.Inventory; +import com.dfsek.terra.api.platform.inventory.ItemStack; +import com.dfsek.terra.fabric.world.FabricAdapter; +import net.minecraft.item.Items; + +public class FabricInventory implements Inventory { + private final net.minecraft.inventory.Inventory delegate; + + public FabricInventory(net.minecraft.inventory.Inventory delegate) { + this.delegate = delegate; + } + + @Override + public net.minecraft.inventory.Inventory getHandle() { + return delegate; + } + + @Override + public int getSize() { + return delegate.size(); + } + + @Override + public ItemStack getItem(int slot) { + net.minecraft.item.ItemStack itemStack = delegate.getStack(slot); + return itemStack.getItem() == Items.AIR ? null : FabricAdapter.adapt(itemStack); + } + + @Override + public void setItem(int slot, ItemStack newStack) { + delegate.setStack(slot, FabricAdapter.adapt(newStack)); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItem.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItem.java new file mode 100644 index 000000000..40c683119 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItem.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.fabric.inventory; + +import com.dfsek.terra.api.platform.inventory.Item; +import com.dfsek.terra.api.platform.inventory.ItemStack; + +public class FabricItem implements Item { + private final net.minecraft.item.Item delegate; + + public FabricItem(net.minecraft.item.Item delegate) { + this.delegate = delegate; + } + + @Override + public net.minecraft.item.Item getHandle() { + return delegate; + } + + @Override + public ItemStack newItemStack(int amount) { + return new FabricItemStack(new net.minecraft.item.ItemStack(delegate, amount)); + } + + @Override + public double getMaxDurability() { + return delegate.getMaxDamage(); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemHandle.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemHandle.java index 2c0596b5e..ef77d9928 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemHandle.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemHandle.java @@ -1,26 +1,36 @@ package com.dfsek.terra.fabric.inventory; -import com.dfsek.terra.api.platform.block.MaterialData; import com.dfsek.terra.api.platform.handle.ItemHandle; -import com.dfsek.terra.api.platform.inventory.ItemStack; +import com.dfsek.terra.api.platform.inventory.Item; import com.dfsek.terra.api.platform.inventory.item.Enchantment; +import com.dfsek.terra.fabric.world.FabricAdapter; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.command.argument.ItemStackArgumentType; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; -import java.util.Collections; import java.util.Set; +import java.util.stream.Collectors; public class FabricItemHandle implements ItemHandle { + @Override - public ItemStack newItemStack(MaterialData material, int amount) { - return null; + public Item createItem(String data) { + try { + return FabricAdapter.adapt(new ItemStackArgumentType().parse(new StringReader(data)).getItem()); + } catch(CommandSyntaxException e) { + throw new IllegalArgumentException("Invalid item data \"" + data + "\"", e); + } } @Override public Enchantment getEnchantment(String id) { - return null; + return FabricAdapter.adapt(Registry.ENCHANTMENT.get(Identifier.tryParse(id))); } @Override public Set getEnchantments() { - return Collections.emptySet(); + return Registry.ENCHANTMENT.stream().map(FabricAdapter::adapt).collect(Collectors.toSet()); } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemStack.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemStack.java index c6caae3e3..19d33b524 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemStack.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemStack.java @@ -1,11 +1,17 @@ package com.dfsek.terra.fabric.inventory; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.inventory.Item; import com.dfsek.terra.api.platform.inventory.ItemStack; import com.dfsek.terra.api.platform.inventory.item.ItemMeta; +import com.dfsek.terra.fabric.inventory.meta.FabricDamageable; +import com.dfsek.terra.fabric.inventory.meta.FabricItemMeta; public class FabricItemStack implements ItemStack { - net.minecraft.item.ItemStack delegate; + private net.minecraft.item.ItemStack delegate; + + public FabricItemStack(net.minecraft.item.ItemStack delegate) { + this.delegate = delegate; + } @Override public int getAmount() { @@ -18,27 +24,23 @@ public class FabricItemStack implements ItemStack { } @Override - public MaterialData getType() { - return null; - } - - @Override - public ItemStack clone() { - return null; + public Item getType() { + return new FabricItem(delegate.getItem()); } @Override public ItemMeta getItemMeta() { - return null; + if(delegate.isDamageable()) return new FabricDamageable(delegate.copy()); + return new FabricItemMeta(delegate.copy()); } @Override public void setItemMeta(ItemMeta meta) { - + this.delegate = ((FabricItemMeta) meta).getHandle(); } @Override - public Object getHandle() { + public net.minecraft.item.ItemStack getHandle() { return delegate; } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/meta/FabricDamageable.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/meta/FabricDamageable.java new file mode 100644 index 000000000..4a4cc918e --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/meta/FabricDamageable.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.fabric.inventory.meta; + +import com.dfsek.terra.api.platform.inventory.item.Damageable; +import net.minecraft.item.ItemStack; + +public class FabricDamageable extends FabricItemMeta implements Damageable { + public FabricDamageable(ItemStack delegate) { + super(delegate); + } + + @Override + public int getDamage() { + return delegate.getDamage(); + } + + @Override + public void setDamage(int damage) { + delegate.setDamage(damage); + } + + @Override + public boolean hasDamage() { + return delegate.isDamageable(); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/meta/FabricItemMeta.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/meta/FabricItemMeta.java new file mode 100644 index 000000000..2c4d9d079 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/meta/FabricItemMeta.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.fabric.inventory.meta; + +import com.dfsek.terra.api.platform.inventory.item.Enchantment; +import com.dfsek.terra.api.platform.inventory.item.ItemMeta; +import com.dfsek.terra.fabric.world.FabricAdapter; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.registry.Registry; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class FabricItemMeta implements ItemMeta { + protected final ItemStack delegate; + + public FabricItemMeta(ItemStack delegate) { + this.delegate = delegate; + } + + @Override + public ItemStack getHandle() { + return delegate; + } + + @Override + public Map getEnchantments() { + if(!delegate.hasEnchantments()) return Collections.emptyMap(); + Map map = new HashMap<>(); + + delegate.getEnchantments().forEach(enchantment -> { + CompoundTag eTag = (CompoundTag) enchantment; + map.put(FabricAdapter.adapt(Registry.ENCHANTMENT.get(eTag.getInt("id"))), eTag.getInt("lvl")); + }); + return map; + } + + @Override + public void addEnchantment(Enchantment enchantment, int level) { + delegate.addEnchantment(FabricAdapter.adapt(enchantment), level); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/GeneratorTypeAccessor.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/GeneratorTypeAccessor.java index e251ebd59..07449ae3a 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/GeneratorTypeAccessor.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/GeneratorTypeAccessor.java @@ -1,15 +1,21 @@ package com.dfsek.terra.fabric.mixin; import net.minecraft.client.world.GeneratorType; +import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.gen.Accessor; import java.util.List; @Mixin(GeneratorType.class) public interface GeneratorTypeAccessor { - @Accessor("VALUES") - static List getValues() { - throw new AssertionError(); + @Accessor + static List getVALUES() { + throw new UnsupportedOperationException(); } + + @Mutable + @Accessor + void setTranslationKey(Text translationKey); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/MixinGeneratorOptions.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/MixinGeneratorOptions.java new file mode 100644 index 000000000..aa588249a --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/MixinGeneratorOptions.java @@ -0,0 +1,62 @@ +package com.dfsek.terra.fabric.mixin; + +import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.fabric.TerraFabricPlugin; +import com.dfsek.terra.fabric.world.TerraBiomeSource; +import com.dfsek.terra.fabric.world.generator.FabricChunkGeneratorWrapper; +import com.google.common.base.MoreObjects; +import net.minecraft.util.registry.DynamicRegistryManager; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.SimpleRegistry; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.dimension.DimensionOptions; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.gen.GeneratorOptions; +import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Properties; +import java.util.Random; + +// Mixins commented out until loom fixes multi-project builds. + +//@Mixin(GeneratorOptions.class) +public class MixinGeneratorOptions { + //@Inject(method = "fromProperties(Lnet/minecraft/util/registry/DynamicRegistryManager;Ljava/util/Properties;)Lnet/minecraft/world/gen/GeneratorOptions;", at = @At("HEAD"), cancellable = true) + private static void fromProperties(DynamicRegistryManager dynamicRegistryManager, Properties properties, CallbackInfoReturnable cir) { + if(properties.get("level-type") == null) { + return; + } + + String prop = properties.get("level-type").toString().trim(); + if(prop.startsWith("Terra")) { + String seed = (String) MoreObjects.firstNonNull(properties.get("level-seed"), ""); + long l = new Random().nextLong(); + if(!seed.isEmpty()) { + try { + long m = Long.parseLong(seed); + if(m != 0L) { + l = m; + } + } catch(NumberFormatException exception) { + l = seed.hashCode(); + } + } + + String generate_structures = (String) properties.get("generate-structures"); + boolean generateStructures = generate_structures == null || Boolean.parseBoolean(generate_structures); + Registry dimensionTypes = dynamicRegistryManager.get(Registry.DIMENSION_TYPE_KEY); + Registry biomes = dynamicRegistryManager.get(Registry.BIOME_KEY); + Registry chunkGeneratorSettings = dynamicRegistryManager.get(Registry.NOISE_SETTINGS_WORLDGEN); + SimpleRegistry dimensionOptions = DimensionType.createDefaultDimensionOptions(dimensionTypes, biomes, chunkGeneratorSettings, l); + + prop = prop.substring(prop.indexOf(":") + 1); + + ConfigPack pack = TerraFabricPlugin.getInstance().getConfigRegistry().get(prop); + + if(pack == null) throw new IllegalArgumentException("No such pack " + prop); + + cir.setReturnValue(new GeneratorOptions(l, generateStructures, false, GeneratorOptions.method_28608(dimensionTypes, dimensionOptions, new FabricChunkGeneratorWrapper(new TerraBiomeSource(biomes, l, pack), l, pack)))); + } + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricAdapter.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricAdapter.java new file mode 100644 index 000000000..e151013f0 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricAdapter.java @@ -0,0 +1,127 @@ +package com.dfsek.terra.fabric.world; + +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.BlockType; +import com.dfsek.terra.api.platform.entity.EntityType; +import com.dfsek.terra.api.platform.inventory.item.Enchantment; +import com.dfsek.terra.fabric.inventory.FabricEnchantment; +import com.dfsek.terra.fabric.inventory.FabricItem; +import com.dfsek.terra.fabric.inventory.FabricItemStack; +import com.dfsek.terra.fabric.world.block.FabricBlockData; +import com.dfsek.terra.fabric.world.block.FabricBlockType; +import com.dfsek.terra.fabric.world.block.data.FabricDirectional; +import com.dfsek.terra.fabric.world.block.data.FabricMultipleFacing; +import com.dfsek.terra.fabric.world.block.data.FabricOrientable; +import com.dfsek.terra.fabric.world.block.data.FabricRotatable; +import com.dfsek.terra.fabric.world.block.data.FabricSlab; +import com.dfsek.terra.fabric.world.block.data.FabricStairs; +import com.dfsek.terra.fabric.world.block.data.FabricWaterlogged; +import com.dfsek.terra.fabric.world.entity.FabricCommandSender; +import com.dfsek.terra.fabric.world.entity.FabricEntityType; +import com.dfsek.terra.fabric.world.entity.FabricPlayer; +import com.dfsek.terra.fabric.world.handles.world.FabricWorldHandle; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.state.property.Properties; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.WorldAccess; + +import java.util.Arrays; + +public final class FabricAdapter { + public static BlockPos adapt(Vector3 v) { + return new BlockPos(v.getBlockX(), v.getBlockY(), v.getBlockZ()); + } + + public static Vector3 adapt(BlockPos pos) { + return new Vector3(pos.getX(), pos.getY(), pos.getZ()); + } + + public static FabricBlockData adapt(BlockState state) { + if(state.contains(Properties.STAIR_SHAPE)) return new FabricStairs(state); + + if(state.contains(Properties.SLAB_TYPE)) return new FabricSlab(state); + + if(state.contains(Properties.AXIS)) return new FabricOrientable(state, Properties.AXIS); + if(state.contains(Properties.HORIZONTAL_AXIS)) return new FabricOrientable(state, Properties.HORIZONTAL_AXIS); + + if(state.contains(Properties.ROTATION)) return new FabricRotatable(state); + + if(state.contains(Properties.FACING)) return new FabricDirectional(state, Properties.FACING); + if(state.contains(Properties.HOPPER_FACING)) return new FabricDirectional(state, Properties.HOPPER_FACING); + if(state.contains(Properties.HORIZONTAL_FACING)) return new FabricDirectional(state, Properties.HORIZONTAL_FACING); + + if(state.getProperties().containsAll(Arrays.asList(Properties.NORTH, Properties.SOUTH, Properties.EAST, Properties.WEST))) + return new FabricMultipleFacing(state); + if(state.contains(Properties.WATERLOGGED)) return new FabricWaterlogged(state); + return new FabricBlockData(state); + } + + public static CommandSender adapt(ServerCommandSource serverCommandSource) { + if(serverCommandSource.getEntity() instanceof PlayerEntity) return new FabricPlayer((PlayerEntity) serverCommandSource.getEntity()); + return new FabricCommandSender(serverCommandSource); + } + + public static Direction adapt(BlockFace face) { + switch(face) { + case NORTH: + return Direction.NORTH; + case WEST: + return Direction.WEST; + case SOUTH: + return Direction.SOUTH; + case EAST: + return Direction.EAST; + case UP: + return Direction.UP; + case DOWN: + return Direction.DOWN; + default: + throw new IllegalArgumentException("Illegal direction: " + face); + } + } + + public static BlockType adapt(Block block) { + return new FabricBlockType(block); + } + + public static EntityType adapt(net.minecraft.entity.EntityType entityType) { + return new FabricEntityType(entityType); + } + + public static net.minecraft.entity.EntityType adapt(EntityType entityType) { + return ((FabricEntityType) entityType).getHandle(); + } + + public static ItemStack adapt(com.dfsek.terra.api.platform.inventory.ItemStack itemStack) { + return ((FabricItemStack) itemStack).getHandle(); + } + + public static com.dfsek.terra.api.platform.inventory.ItemStack adapt(ItemStack itemStack) { + return new FabricItemStack(itemStack); + } + + public static com.dfsek.terra.api.platform.inventory.Item adapt(Item item) { + return new FabricItem(item); + } + + public static Enchantment adapt(net.minecraft.enchantment.Enchantment enchantment) { + return new FabricEnchantment(enchantment); + } + + public static net.minecraft.enchantment.Enchantment adapt(Enchantment enchantment) { + return ((FabricEnchantment) enchantment).getHandle(); + } + + public WorldAccess adapt(FabricWorldHandle worldHandle) { + return worldHandle.getWorld(); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricAdapters.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricAdapters.java deleted file mode 100644 index a65e456d5..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricAdapters.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.fabric.world; - -import com.dfsek.terra.api.math.vector.Vector3; -import net.minecraft.util.math.BlockPos; - -public final class FabricAdapters { - public static BlockPos fromVector(Vector3 v) { - return new BlockPos(v.getBlockX(), v.getBlockY(), v.getBlockZ()); - } - - public static Vector3 toVector(BlockPos pos) { - return new Vector3(pos.getX(), pos.getY(), pos.getZ()); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricTree.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricTree.java index 603202480..1055c0964 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricTree.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricTree.java @@ -1,19 +1,17 @@ package com.dfsek.terra.fabric.world; import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.world.tree.Tree; import com.dfsek.terra.fabric.TerraFabricPlugin; import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator; import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess; -import com.dfsek.terra.util.MaterialSet; import net.minecraft.util.math.BlockPos; import net.minecraft.world.StructureWorldAccess; import net.minecraft.world.gen.chunk.ChunkGenerator; import net.minecraft.world.gen.feature.ConfiguredFeature; import java.util.Random; -import java.util.Set; public class FabricTree implements Tree { private final ConfiguredFeature delegate; @@ -30,8 +28,9 @@ public class FabricTree implements Tree { } @Override - public Set getSpawnable() { - return MaterialSet.get(TerraFabricPlugin.getInstance().getWorldHandle().createMaterialData("minecraft:grass_block"), - TerraFabricPlugin.getInstance().getWorldHandle().createMaterialData("minecraft:podzol")); + public MaterialSet getSpawnable() { + return MaterialSet.get(TerraFabricPlugin.getInstance().getWorldHandle().createBlockData("minecraft:grass_block"), + TerraFabricPlugin.getInstance().getWorldHandle().createBlockData("minecraft:podzol"), + TerraFabricPlugin.getInstance().getWorldHandle().createBlockData("minecraft:mycelium")); } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricWorldHandle.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricWorldHandle.java index e06e8e780..8d6919d56 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricWorldHandle.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricWorldHandle.java @@ -1,40 +1,18 @@ package com.dfsek.terra.fabric.world; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; import com.dfsek.terra.api.platform.entity.EntityType; import com.dfsek.terra.api.platform.handle.WorldHandle; import com.dfsek.terra.fabric.world.block.FabricBlockData; -import com.dfsek.terra.fabric.world.block.FabricMaterialData; -import com.dfsek.terra.fabric.world.block.data.FabricMultipleFacing; -import com.dfsek.terra.fabric.world.block.data.FabricOrientable; -import com.dfsek.terra.fabric.world.block.data.FabricSlab; -import com.dfsek.terra.fabric.world.block.data.FabricStairs; -import com.dfsek.terra.fabric.world.block.data.FabricWaterlogged; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.block.BlockState; import net.minecraft.command.argument.BlockArgumentParser; -import net.minecraft.state.property.Properties; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; -import java.util.Arrays; +import java.util.Locale; public class FabricWorldHandle implements WorldHandle { - @Override - public void setBlockData(Block block, BlockData data, boolean physics) { - block.setBlockData(data, physics); - } - - @Override - public BlockData getBlockData(Block block) { - return block.getBlockData(); - } - - @Override - public MaterialData getType(Block block) { - return block.getType(); - } @Override public FabricBlockData createBlockData(String data) { @@ -42,29 +20,16 @@ public class FabricWorldHandle implements WorldHandle { try { BlockState state = parser.parse(true).getBlockState(); if(state == null) throw new IllegalArgumentException("Invalid data: " + data); - - if(state.contains(Properties.STAIR_SHAPE)) return new FabricStairs(state); - - if(state.contains(Properties.SLAB_TYPE)) return new FabricSlab(state); - - if(state.contains(Properties.AXIS)) return new FabricOrientable(state); - - if(state.getProperties().containsAll(Arrays.asList(Properties.NORTH, Properties.SOUTH, Properties.EAST, Properties.WEST))) - return new FabricMultipleFacing(state); - if(state.contains(Properties.WATERLOGGED)) return new FabricWaterlogged(state); - return new FabricBlockData(state); + return FabricAdapter.adapt(state); } catch(CommandSyntaxException e) { throw new IllegalArgumentException(e); } } - @Override - public MaterialData createMaterialData(String data) { - return new FabricMaterialData(createBlockData(data).getHandle().getBlock()); - } - @Override public EntityType getEntity(String id) { - return null; + Identifier identifier = Identifier.tryParse(id); + if(identifier == null) identifier = Identifier.tryParse("minecraft:" + id.toLowerCase(Locale.ROOT)); + return FabricAdapter.adapt(Registry.ENTITY_TYPE.get(identifier)); } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/TerraBiomeSource.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/TerraBiomeSource.java index 8cc0dee3d..46b628eac 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/TerraBiomeSource.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/TerraBiomeSource.java @@ -1,7 +1,7 @@ package com.dfsek.terra.fabric.world; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; +import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.fabric.TerraFabricPlugin; import com.mojang.serialization.Codec; @@ -18,7 +18,7 @@ import java.util.stream.Collectors; public class TerraBiomeSource extends BiomeSource { public static final Codec PACK_CODEC = (RecordCodecBuilder.create(config -> config.group( Codec.STRING.fieldOf("pack").forGetter(pack -> pack.getTemplate().getID()) - ).apply(config, config.stable(TerraFabricPlugin.getInstance().getRegistry()::get)))); + ).apply(config, config.stable(TerraFabricPlugin.getInstance().getConfigRegistry()::get)))); public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( RegistryLookupCodec.of(Registry.BIOME_KEY).forGetter(source -> source.biomeRegistry), Codec.LONG.fieldOf("seed").stable().forGetter(source -> source.seed), @@ -50,8 +50,8 @@ public class TerraBiomeSource extends BiomeSource { @Override public Biome getBiomeForNoiseGen(int biomeX, int biomeY, int biomeZ) { - UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(biomeX * 4, biomeZ * 4); - return biomeRegistry.get(new Identifier("terra", TerraFabricPlugin.createBiomeID(pack, biome))); + UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(biomeX << 2, biomeZ << 2); + return biomeRegistry.get(new Identifier("terra", TerraFabricPlugin.createBiomeID(pack, biome.getID()))); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlock.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlock.java index 2b22b99ba..9379380ca 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlock.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlock.java @@ -4,9 +4,10 @@ import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.block.BlockType; import com.dfsek.terra.api.platform.block.state.BlockState; -import com.dfsek.terra.fabric.world.FabricAdapters; +import com.dfsek.terra.fabric.world.FabricAdapter; +import com.dfsek.terra.fabric.world.block.state.FabricBlockState; import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess; import net.minecraft.util.math.BlockPos; import net.minecraft.world.WorldAccess; @@ -20,7 +21,7 @@ public class FabricBlock implements Block { @Override public void setBlockData(BlockData data, boolean physics) { - delegate.worldAccess.setBlockState(delegate.position, ((FabricBlockData) data).getHandle(), 0, 0); + delegate.worldAccess.setBlockState(delegate.position, ((FabricBlockData) data).getHandle(), physics ? 3 : 1042, 0); } @Override @@ -30,12 +31,7 @@ public class FabricBlock implements Block { @Override public BlockState getState() { - return null; - } - - @Override - public Block getRelative(BlockFace face) { - return getRelative(face, 1); + return FabricBlockState.newInstance(this); } @Override @@ -46,17 +42,17 @@ public class FabricBlock implements Block { @Override public boolean isEmpty() { - return getBlockData().getMaterial().isAir(); + return getBlockData().isAir(); } @Override public Location getLocation() { - return FabricAdapters.toVector(delegate.position).toLocation(new FabricWorldAccess(delegate.worldAccess)); + return FabricAdapter.adapt(delegate.position).toLocation(new FabricWorldAccess(delegate.worldAccess)); } @Override - public MaterialData getType() { - return getBlockData().getMaterial(); + public BlockType getType() { + return getBlockData().getBlockType(); } @Override diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlockData.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlockData.java index f7fac5fb4..2467e992a 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlockData.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlockData.java @@ -1,8 +1,14 @@ package com.dfsek.terra.fabric.world.block; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.block.BlockType; +import com.dfsek.terra.fabric.world.FabricAdapter; import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.state.State; +import net.minecraft.util.registry.Registry; + +import java.util.stream.Collectors; public class FabricBlockData implements BlockData { protected BlockState delegate; @@ -12,13 +18,13 @@ public class FabricBlockData implements BlockData { } @Override - public MaterialData getMaterial() { - return new FabricMaterialData(delegate.getBlock()); + public BlockType getBlockType() { + return FabricAdapter.adapt(delegate.getBlock()); } @Override - public boolean matches(MaterialData materialData) { - return ((FabricMaterialData) materialData).getHandle().is(delegate.getBlock()); + public boolean matches(BlockData other) { + return delegate.getBlock() == ((FabricBlockData) other).delegate.getBlock(); } @Override @@ -32,7 +38,23 @@ public class FabricBlockData implements BlockData { @Override public String getAsString() { - return delegate.toString(); + StringBuilder data = new StringBuilder(Registry.BLOCK.getId(delegate.getBlock()).toString()); + if(!delegate.getEntries().isEmpty()) { + data.append('['); + data.append(delegate.getEntries().entrySet().stream().map(State.PROPERTY_MAP_PRINTER).collect(Collectors.joining(","))); + data.append(']'); + } + return data.toString(); + } + + @Override + public boolean isAir() { + return delegate.isAir(); + } + + @Override + public boolean isStructureVoid() { + return delegate.getBlock() == Blocks.STRUCTURE_VOID; } @Override diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlockType.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlockType.java new file mode 100644 index 000000000..ae72e4caa --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlockType.java @@ -0,0 +1,40 @@ +package com.dfsek.terra.fabric.world.block; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockType; +import com.dfsek.terra.fabric.world.FabricAdapter; +import net.minecraft.block.Block; + +public class FabricBlockType implements BlockType { + private final Block delegate; + + public FabricBlockType(Block delegate) { + this.delegate = delegate; + } + + @Override + public Block getHandle() { + return delegate; + } + + @Override + public BlockData getDefaultData() { + return FabricAdapter.adapt(delegate.getDefaultState()); + } + + @Override + public boolean isSolid() { + return delegate.getDefaultState().isOpaque(); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof FabricBlockType)) return false; + return ((FabricBlockType) obj).delegate == delegate; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricMaterialData.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricMaterialData.java deleted file mode 100644 index dd9941d03..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricMaterialData.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.dfsek.terra.fabric.world.block; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; -import net.minecraft.block.Block; -import net.minecraft.block.Blocks; - -public class FabricMaterialData implements MaterialData { - private final Block delegate; - - public FabricMaterialData(Block delegate) { - this.delegate = delegate; - } - - @Override - public boolean matches(MaterialData other) { - return delegate.equals(((FabricMaterialData) other).getHandle()); - } - - @Override - public boolean matches(BlockData other) { - return delegate.equals(((FabricMaterialData) other.getMaterial()).getHandle()); - } - - @Override - public boolean isSolid() { - return !delegate.is(Blocks.AIR); - } - - @Override - public boolean isAir() { - return delegate.is(Blocks.AIR); // TODO: better impl - } - - @Override - public double getMaxDurability() { - return 0; - } - - @Override - public BlockData createBlockData() { - return new FabricBlockData(delegate.getDefaultState()); - } - - @Override - public Block getHandle() { - return delegate; - } - - - @Override - public int hashCode() { - return delegate.asItem().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if(obj instanceof FabricMaterialData) { - return ((FabricMaterialData) obj).matches(this); - } - return false; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricDirectional.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricDirectional.java new file mode 100644 index 000000000..21584a8e8 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricDirectional.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.fabric.world.block.data; + +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.Directional; +import com.dfsek.terra.fabric.world.FabricAdapter; +import com.dfsek.terra.fabric.world.block.FabricBlockData; +import net.minecraft.block.BlockState; +import net.minecraft.state.property.DirectionProperty; + +public class FabricDirectional extends FabricBlockData implements Directional { + private final DirectionProperty property; + + public FabricDirectional(BlockState delegate, DirectionProperty property) { + super(delegate); + this.property = property; + } + + @Override + public BlockFace getFacing() { + switch(delegate.get(property)) { + case SOUTH: + return BlockFace.SOUTH; + case DOWN: + return BlockFace.DOWN; + case UP: + return BlockFace.UP; + case EAST: + return BlockFace.EAST; + case WEST: + return BlockFace.WEST; + case NORTH: + return BlockFace.NORTH; + default: + throw new IllegalStateException(); + } + } + + @Override + public void setFacing(BlockFace facing) { + delegate = delegate.with(property, FabricAdapter.adapt(facing)); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricOrientable.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricOrientable.java index c817a917a..5c9e179d0 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricOrientable.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricOrientable.java @@ -4,15 +4,19 @@ import com.dfsek.terra.api.platform.block.Axis; import com.dfsek.terra.api.platform.block.data.Orientable; import com.dfsek.terra.fabric.world.block.FabricBlockData; import net.minecraft.block.BlockState; -import net.minecraft.state.property.Properties; +import net.minecraft.state.property.EnumProperty; +import net.minecraft.util.math.Direction; import java.util.Arrays; import java.util.Set; import java.util.stream.Collectors; public class FabricOrientable extends FabricBlockData implements Orientable { - public FabricOrientable(BlockState delegate) { + private final EnumProperty property; + + public FabricOrientable(BlockState delegate, EnumProperty property) { super(delegate); + this.property = property; } @Override @@ -22,11 +26,11 @@ public class FabricOrientable extends FabricBlockData implements Orientable { @Override public Axis getAxis() { - return FabricEnumAdapter.adapt(getHandle().get(Properties.AXIS)); + return FabricEnumAdapter.adapt(getHandle().get(property)); } @Override public void setAxis(Axis axis) { - delegate = delegate.with(Properties.AXIS, FabricEnumAdapter.adapt(axis)); + delegate = delegate.with(property, FabricEnumAdapter.adapt(axis)); } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricRotatable.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricRotatable.java new file mode 100644 index 000000000..a238f21e1 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricRotatable.java @@ -0,0 +1,111 @@ +package com.dfsek.terra.fabric.world.block.data; + +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.Rotatable; +import com.dfsek.terra.fabric.world.block.FabricBlockData; +import net.minecraft.block.BlockState; +import net.minecraft.state.property.Properties; + +public class FabricRotatable extends FabricBlockData implements Rotatable { + public FabricRotatable(BlockState delegate) { + super(delegate); + } + + @Override + public BlockFace getRotation() { + int r = delegate.get(Properties.ROTATION); + switch(r) { + case 0: + return BlockFace.SOUTH; + case 1: + return BlockFace.SOUTH_SOUTH_WEST; + case 2: + return BlockFace.SOUTH_WEST; + case 3: + return BlockFace.WEST_SOUTH_WEST; + case 4: + return BlockFace.WEST; + case 5: + return BlockFace.WEST_NORTH_WEST; + case 6: + return BlockFace.NORTH_WEST; + case 7: + return BlockFace.NORTH_NORTH_WEST; + case 8: + return BlockFace.NORTH; + case 9: + return BlockFace.NORTH_NORTH_EAST; + case 10: + return BlockFace.NORTH_EAST; + case 11: + return BlockFace.EAST_NORTH_EAST; + case 12: + return BlockFace.EAST; + case 13: + return BlockFace.EAST_SOUTH_EAST; + case 14: + return BlockFace.SOUTH_EAST; + case 15: + return BlockFace.SOUTH_SOUTH_EAST; + default: + throw new IllegalArgumentException("Unknown rotation " + r); + } + } + + @Override + public void setRotation(BlockFace face) { + switch(face) { + case UP: + case DOWN: + throw new IllegalArgumentException("Illegal rotation " + face); + case SOUTH: + delegate = delegate.with(Properties.ROTATION, 0); + return; + case SOUTH_SOUTH_WEST: + delegate = delegate.with(Properties.ROTATION, 1); + return; + case SOUTH_WEST: + delegate = delegate.with(Properties.ROTATION, 2); + return; + case WEST_SOUTH_WEST: + delegate = delegate.with(Properties.ROTATION, 3); + return; + case WEST: + delegate = delegate.with(Properties.ROTATION, 4); + return; + case WEST_NORTH_WEST: + delegate = delegate.with(Properties.ROTATION, 5); + return; + case NORTH_WEST: + delegate = delegate.with(Properties.ROTATION, 6); + return; + case NORTH_NORTH_WEST: + delegate = delegate.with(Properties.ROTATION, 7); + return; + case NORTH: + delegate = delegate.with(Properties.ROTATION, 8); + return; + case NORTH_NORTH_EAST: + delegate = delegate.with(Properties.ROTATION, 9); + return; + case NORTH_EAST: + delegate = delegate.with(Properties.ROTATION, 10); + return; + case EAST_NORTH_EAST: + delegate = delegate.with(Properties.ROTATION, 11); + return; + case EAST: + delegate = delegate.with(Properties.ROTATION, 12); + return; + case EAST_SOUTH_EAST: + delegate = delegate.with(Properties.ROTATION, 13); + return; + case SOUTH_EAST: + delegate = delegate.with(Properties.ROTATION, 14); + return; + case SOUTH_SOUTH_EAST: + delegate = delegate.with(Properties.ROTATION, 15); + return; + } + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricBlockState.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricBlockState.java new file mode 100644 index 000000000..d0dbf5bf4 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricBlockState.java @@ -0,0 +1,73 @@ +package com.dfsek.terra.fabric.world.block.state; + +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.state.BlockState; +import com.dfsek.terra.fabric.world.FabricAdapter; +import com.dfsek.terra.fabric.world.block.FabricBlock; +import com.dfsek.terra.fabric.world.handles.world.FabricWorldHandle; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.LootableContainerBlockEntity; +import net.minecraft.block.entity.MobSpawnerBlockEntity; +import net.minecraft.block.entity.SignBlockEntity; +import net.minecraft.world.WorldAccess; + +public class FabricBlockState implements BlockState { + protected final BlockEntity blockEntity; + private final WorldAccess worldAccess; + + public FabricBlockState(BlockEntity blockEntity, WorldAccess worldAccess) { + this.blockEntity = blockEntity; + this.worldAccess = worldAccess; + } + + public static FabricBlockState newInstance(Block block) { + WorldAccess worldAccess = ((FabricWorldHandle) block.getLocation().getWorld()).getWorld(); + + BlockEntity entity = worldAccess.getBlockEntity(FabricAdapter.adapt(block.getLocation().toVector())); + if(entity instanceof SignBlockEntity) { + return new FabricSign((SignBlockEntity) entity, worldAccess); + } else if(entity instanceof MobSpawnerBlockEntity) { + return new FabricMobSpawner((MobSpawnerBlockEntity) entity, worldAccess); + } else if(entity instanceof LootableContainerBlockEntity) { + return new FabricContainer((LootableContainerBlockEntity) entity, worldAccess); + } + return null; + } + + @Override + public BlockEntity getHandle() { + return blockEntity; + } + + @Override + public Block getBlock() { + return new FabricBlock(blockEntity.getPos(), blockEntity.getWorld()); + } + + @Override + public int getX() { + return blockEntity.getPos().getX(); + } + + @Override + public int getY() { + return blockEntity.getPos().getY(); + } + + @Override + public int getZ() { + return blockEntity.getPos().getZ(); + } + + @Override + public BlockData getBlockData() { + return FabricAdapter.adapt(blockEntity.getCachedState()); + } + + @Override + public boolean update(boolean applyPhysics) { + worldAccess.getChunk(blockEntity.getPos()).setBlockEntity(blockEntity.getPos(), blockEntity); + return true; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricContainer.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricContainer.java new file mode 100644 index 000000000..743c06d83 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricContainer.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.fabric.world.block.state; + +import com.dfsek.terra.api.platform.block.state.Container; +import com.dfsek.terra.api.platform.inventory.Inventory; +import com.dfsek.terra.fabric.inventory.FabricInventory; +import net.minecraft.block.entity.LootableContainerBlockEntity; +import net.minecraft.world.WorldAccess; + +public class FabricContainer extends FabricBlockState implements Container { + public FabricContainer(LootableContainerBlockEntity blockEntity, WorldAccess worldAccess) { + super(blockEntity, worldAccess); + } + + @Override + public Inventory getInventory() { + return new FabricInventory(((LootableContainerBlockEntity) blockEntity)); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricMobSpawner.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricMobSpawner.java new file mode 100644 index 000000000..8486e20c9 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricMobSpawner.java @@ -0,0 +1,133 @@ +package com.dfsek.terra.fabric.world.block.state; + +import com.dfsek.terra.api.platform.block.state.MobSpawner; +import com.dfsek.terra.api.platform.block.state.SerialState; +import com.dfsek.terra.api.platform.entity.EntityType; +import com.dfsek.terra.fabric.TerraFabricPlugin; +import com.dfsek.terra.fabric.world.FabricAdapter; +import net.minecraft.block.entity.MobSpawnerBlockEntity; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.WorldAccess; +import org.jetbrains.annotations.NotNull; + +public class FabricMobSpawner extends FabricBlockState implements MobSpawner { // TODO: finish implementation / refactor API because bukkit doesnt expose most of the stuff spawners can do + + + public FabricMobSpawner(MobSpawnerBlockEntity blockEntity, WorldAccess worldAccess) { + super(blockEntity, worldAccess); + } + + @Override + public EntityType getSpawnedType() { + return FabricAdapter.adapt(Registry.ENTITY_TYPE.get(((MobSpawnerBlockEntity) blockEntity).getLogic().getEntityId())); + } + + @Override + public void setSpawnedType(@NotNull EntityType creatureType) { + ((MobSpawnerBlockEntity) blockEntity).getLogic().setEntityId(FabricAdapter.adapt(creatureType)); + } + + @Override + public int getDelay() { + return 0; + } + + @Override + public void setDelay(int delay) { + + } + + @Override + public int getMinSpawnDelay() { + return 0; + } + + @Override + public void setMinSpawnDelay(int delay) { + + } + + @Override + public int getMaxSpawnDelay() { + return 0; + } + + @Override + public void setMaxSpawnDelay(int delay) { + + } + + @Override + public int getSpawnCount() { + return 0; + } + + @Override + public void setSpawnCount(int spawnCount) { + + } + + @Override + public int getMaxNearbyEntities() { + return 0; + } + + @Override + public void setMaxNearbyEntities(int maxNearbyEntities) { + + } + + @Override + public int getRequiredPlayerRange() { + return 0; + } + + @Override + public void setRequiredPlayerRange(int requiredPlayerRange) { + + } + + @Override + public int getSpawnRange() { + return 0; + } + + @Override + public void setSpawnRange(int spawnRange) { + + } + + @Override + public void applyState(String state) { + SerialState.parse(state).forEach((k, v) -> { + switch(k) { + case "type": + setSpawnedType(TerraFabricPlugin.getInstance().getWorldHandle().getEntity(v)); + return; + case "delay": + setDelay(Integer.parseInt(v)); + return; + case "min_delay": + setMinSpawnDelay(Integer.parseInt(v)); + return; + case "max_delay": + setMaxSpawnDelay(Integer.parseInt(v)); + return; + case "spawn_count": + setSpawnCount(Integer.parseInt(v)); + return; + case "spawn_range": + setSpawnRange(Integer.parseInt(v)); + return; + case "max_nearby": + setMaxNearbyEntities(Integer.parseInt(v)); + return; + case "required_player_range": + setRequiredPlayerRange(Integer.parseInt(v)); + return; + default: + throw new IllegalArgumentException("Invalid property: " + k); + } + }); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricSign.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricSign.java new file mode 100644 index 000000000..382e05387 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricSign.java @@ -0,0 +1,44 @@ +package com.dfsek.terra.fabric.world.block.state; + +import com.dfsek.terra.api.platform.block.state.SerialState; +import com.dfsek.terra.api.platform.block.state.Sign; +import net.minecraft.block.entity.SignBlockEntity; +import net.minecraft.text.LiteralText; +import net.minecraft.world.WorldAccess; +import org.jetbrains.annotations.NotNull; + +public class FabricSign extends FabricBlockState implements Sign { + public FabricSign(SignBlockEntity blockEntity, WorldAccess worldAccess) { + super(blockEntity, worldAccess); + } + + @Override + public @NotNull String[] getLines() { + SignBlockEntity sign = (SignBlockEntity) blockEntity; + + return new String[] { + sign.getTextOnRow(0).asString(), + sign.getTextOnRow(1).asString(), + sign.getTextOnRow(2).asString(), + sign.getTextOnRow(3).asString() + }; + } + + @Override + public @NotNull String getLine(int index) throws IndexOutOfBoundsException { + return ((SignBlockEntity) blockEntity).getTextOnRow(index).asString(); + } + + @Override + public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException { + ((SignBlockEntity) blockEntity).setTextOnRow(index, new LiteralText(line)); + } + + @Override + public void applyState(String state) { + SerialState.parse(state).forEach((k, v) -> { + if(!k.startsWith("text")) throw new IllegalArgumentException("Invalid property: " + k); + setLine(Integer.parseInt(k.substring(4)), v); + }); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricCommandSender.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricCommandSender.java new file mode 100644 index 000000000..e7f946008 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricCommandSender.java @@ -0,0 +1,23 @@ +package com.dfsek.terra.fabric.world.entity; + +import com.dfsek.terra.api.platform.CommandSender; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; + +public class FabricCommandSender implements CommandSender { + private final ServerCommandSource delegate; + + public FabricCommandSender(ServerCommandSource delegate) { + this.delegate = delegate; + } + + @Override + public void sendMessage(String message) { + delegate.sendFeedback(new LiteralText(message), true); + } + + @Override + public Object getHandle() { + return delegate; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricEntity.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricEntity.java new file mode 100644 index 000000000..65c26849d --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricEntity.java @@ -0,0 +1,43 @@ +package com.dfsek.terra.fabric.world.entity; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.entity.Entity; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.fabric.world.FabricAdapter; +import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess; +import com.dfsek.terra.fabric.world.handles.world.FabricWorldHandle; +import net.minecraft.server.world.ServerWorld; + +public class FabricEntity implements Entity { + private final net.minecraft.entity.Entity delegate; + + public FabricEntity(net.minecraft.entity.Entity delegate) { + this.delegate = delegate; + } + + @Override + public void sendMessage(String message) { + + } + + @Override + public Object getHandle() { + return null; + } + + @Override + public Location getLocation() { + return new Location(new FabricWorldAccess(delegate.world), FabricAdapter.adapt(delegate.getBlockPos())); + } + + @Override + public void setLocation(Location location) { + delegate.teleport(location.getX(), location.getY(), location.getZ()); + delegate.moveToWorld((ServerWorld) ((FabricWorldHandle) location).getWorld()); + } + + @Override + public World getWorld() { + return new FabricWorldAccess(delegate.world); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricEntityType.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricEntityType.java new file mode 100644 index 000000000..31d6aceb1 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricEntityType.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.fabric.world.entity; + +import com.dfsek.terra.api.platform.entity.EntityType; + +public class FabricEntityType implements EntityType { + private final net.minecraft.entity.EntityType type; + + public FabricEntityType(net.minecraft.entity.EntityType type) { + this.type = type; + } + + @Override + public net.minecraft.entity.EntityType getHandle() { + return type; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricPlayer.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricPlayer.java new file mode 100644 index 000000000..143ad024c --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricPlayer.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.fabric.world.entity; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.fabric.world.FabricAdapter; +import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.text.LiteralText; + +public class FabricPlayer implements Player { + private final PlayerEntity delegate; + + public FabricPlayer(PlayerEntity delegate) { + this.delegate = delegate; + } + + @Override + public void sendMessage(String message) { + delegate.sendMessage(new LiteralText(message), false); + } + + @Override + public Object getHandle() { + return delegate; + } + + @Override + public Location getLocation() { + return FabricAdapter.adapt(delegate.getBlockPos()).toLocation(new FabricWorldAccess(delegate.world)); + } + + @Override + public World getWorld() { + return new FabricWorldAccess(delegate.world); + } + + @Override + public void setLocation(Location location) { + delegate.teleport(location.getX(), location.getY(), location.getZ()); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/features/PopulatorFeature.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/features/PopulatorFeature.java index 490a14c6b..fdb39fe78 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/features/PopulatorFeature.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/features/PopulatorFeature.java @@ -4,7 +4,7 @@ import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator; import com.dfsek.terra.fabric.world.generator.FabricChunkGeneratorWrapper; import com.dfsek.terra.fabric.world.handles.FabricWorld; import com.dfsek.terra.fabric.world.handles.chunk.FabricChunkWorldAccess; -import com.dfsek.terra.fabric.world.handles.world.FabricSeededWorldAccess; +import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess; import com.mojang.serialization.Codec; import net.minecraft.util.math.BlockPos; import net.minecraft.world.StructureWorldAccess; @@ -27,7 +27,8 @@ public class PopulatorFeature extends Feature { FabricChunkGeneratorWrapper gen = (FabricChunkGeneratorWrapper) chunkGenerator; FabricChunkWorldAccess chunk = new FabricChunkWorldAccess(world, pos.getX() >> 4, pos.getZ() >> 4); FabricWorld world1 = new FabricWorld(world.toServerWorld(), new FabricChunkGenerator(chunkGenerator)); - gen.getStructurePopulator().populate(new FabricSeededWorldAccess(world, world.getSeed(), chunkGenerator), chunk); + gen.getCavePopulator().populate(new FabricWorldAccess(world), chunk); + gen.getStructurePopulator().populate(new FabricWorldAccess(world), chunk); gen.getOrePopulator().populate(world1, chunk); gen.getTreePopulator().populate(world1, chunk); gen.getFloraPopulator().populate(world1, chunk); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkData.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkData.java index 9864c472f..24ea33e9b 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkData.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkData.java @@ -1,13 +1,13 @@ package com.dfsek.terra.fabric.world.generator; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.generator.ChunkData; import com.dfsek.terra.fabric.world.block.FabricBlockData; import net.minecraft.util.math.BlockPos; import net.minecraft.world.chunk.Chunk; import org.jetbrains.annotations.NotNull; -public class FabricChunkData implements ChunkGenerator.ChunkData { +public class FabricChunkData implements ChunkData { private final Chunk handle; public FabricChunkData(Chunk handle) { diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGenerator.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGenerator.java index 52b4c0d5f..ae7526326 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGenerator.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGenerator.java @@ -1,15 +1,6 @@ package com.dfsek.terra.fabric.world.generator; -import com.dfsek.terra.api.platform.world.BiomeGrid; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.BlockPopulator; import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.Random; public class FabricChunkGenerator implements ChunkGenerator { private final net.minecraft.world.gen.chunk.ChunkGenerator delegate; @@ -18,47 +9,6 @@ public class FabricChunkGenerator implements ChunkGenerator { this.delegate = delegate; } - @Override - public boolean isParallelCapable() { - return false; - } - - @Override - public boolean shouldGenerateCaves() { - return false; - } - - @Override - public boolean shouldGenerateDecorations() { - return false; - } - - @Override - public boolean shouldGenerateMobs() { - return false; - } - - @Override - public boolean shouldGenerateStructures() { - return false; - } - - @Override - public ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome) { - return null; - } - - @Override - public List getDefaultPopulators(World world) { - return null; - } - - @Override - public @Nullable TerraChunkGenerator getTerraGenerator() { - if(delegate instanceof FabricChunkGeneratorWrapper) return ((FabricChunkGeneratorWrapper) delegate).getHandle(); - return null; - } - @Override public net.minecraft.world.gen.chunk.ChunkGenerator getHandle() { return delegate; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGeneratorWrapper.java index 898c230d9..cb7ebe8b8 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGeneratorWrapper.java @@ -2,11 +2,13 @@ package com.dfsek.terra.fabric.world.generator; import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.api.world.generation.TerraChunkGenerator; import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.fabric.TerraFabricPlugin; import com.dfsek.terra.fabric.world.TerraBiomeSource; import com.dfsek.terra.fabric.world.handles.world.FabricSeededWorldAccess; -import com.dfsek.terra.world.generation.MasterChunkGenerator; +import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D; +import com.dfsek.terra.world.population.CavePopulator; import com.dfsek.terra.world.population.FloraPopulator; import com.dfsek.terra.world.population.OrePopulator; import com.dfsek.terra.world.population.StructurePopulator; @@ -32,11 +34,11 @@ import net.minecraft.world.gen.chunk.VerticalBlockSample; public class FabricChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper { private final long seed; - private final MasterChunkGenerator delegate; + private final DefaultChunkGenerator3D delegate; private final TerraBiomeSource biomeSource; public static final Codec PACK_CODEC = (RecordCodecBuilder.create(config -> config.group( Codec.STRING.fieldOf("pack").forGetter(pack -> pack.getTemplate().getID()) - ).apply(config, config.stable(TerraFabricPlugin.getInstance().getRegistry()::get)))); + ).apply(config, config.stable(TerraFabricPlugin.getInstance().getConfigRegistry()::get)))); public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( TerraBiomeSource.CODEC.fieldOf("biome_source").forGetter(generator -> generator.biomeSource), Codec.LONG.fieldOf("seed").stable().forGetter(generator -> generator.seed), @@ -44,11 +46,15 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener .apply(instance, instance.stable(FabricChunkGeneratorWrapper::new))); private final ConfigPack pack; + public ConfigPack getPack() { + return pack; + } private final FloraPopulator floraPopulator = new FloraPopulator(TerraFabricPlugin.getInstance()); private final OrePopulator orePopulator = new OrePopulator(TerraFabricPlugin.getInstance()); private final TreePopulator treePopulator = new TreePopulator(TerraFabricPlugin.getInstance()); private final StructurePopulator structurePopulator = new StructurePopulator(TerraFabricPlugin.getInstance()); + private final CavePopulator cavePopulator = new CavePopulator(TerraFabricPlugin.getInstance()); public TreePopulator getTreePopulator() { return treePopulator; @@ -66,21 +72,21 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener return structurePopulator; } + public CavePopulator getCavePopulator() { + return cavePopulator; + } + public FabricChunkGeneratorWrapper(TerraBiomeSource biomeSource, long seed, ConfigPack configPack) { super(biomeSource, new StructuresConfig(false)); this.pack = configPack; - this.delegate = new MasterChunkGenerator(configPack, TerraFabricPlugin.getInstance(), pack.getSamplerCache()); - delegate.getMain().getLogger().info("Loading world..."); + this.delegate = new DefaultChunkGenerator3D(pack, TerraFabricPlugin.getInstance()); + delegate.getMain().logger().info("Loading world with config pack " + pack.getTemplate().getID()); this.biomeSource = biomeSource; this.seed = seed; } - @Override - public MasterChunkGenerator getHandle() { - return delegate; - } @Override protected Codec getCodec() { @@ -97,6 +103,11 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener } + @Override + public void generateFeatures(ChunkRegion region, StructureAccessor accessor) { + super.generateFeatures(region, accessor); + } + @Override public void populateNoise(WorldAccess world, StructureAccessor accessor, Chunk chunk) { FabricSeededWorldAccess worldAccess = new FabricSeededWorldAccess(world, seed, this); @@ -141,4 +152,9 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener return new VerticalBlockSample(array); } + + @Override + public TerraChunkGenerator getHandle() { + return delegate; + } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/FabricWorld.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/FabricWorld.java index df0be992d..097ddfcb1 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/FabricWorld.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/FabricWorld.java @@ -7,15 +7,20 @@ import com.dfsek.terra.api.platform.entity.EntityType; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; +import com.dfsek.terra.fabric.world.FabricAdapter; import com.dfsek.terra.fabric.world.block.FabricBlock; +import com.dfsek.terra.fabric.world.entity.FabricEntity; import com.dfsek.terra.fabric.world.handles.chunk.FabricChunk; +import com.dfsek.terra.fabric.world.handles.world.FabricWorldHandle; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.ServerWorldAccess; +import net.minecraft.world.WorldAccess; import java.io.File; import java.util.UUID; -public class FabricWorld implements World { +public class FabricWorld implements World, FabricWorldHandle { private final Handle delegate; @@ -71,23 +76,26 @@ public class FabricWorld implements World { @Override public int hashCode() { - return delegate.generator.hashCode(); + return ((ServerWorldAccess) delegate.world).toServerWorld().hashCode(); } @Override public boolean equals(Object obj) { if(!(obj instanceof FabricWorld)) return false; - return ((FabricWorld) obj).delegate.generator.equals(delegate.generator); - } - - @Override - public Block getBlockAt(Location l) { - return getBlockAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()); + return ((ServerWorldAccess) ((FabricWorld) obj).delegate.world).toServerWorld().equals(((ServerWorldAccess) delegate.world).toServerWorld()); } @Override public Entity spawnEntity(Location location, EntityType entityType) { - return null; + net.minecraft.entity.Entity entity = FabricAdapter.adapt(entityType).create(delegate.world); + entity.setPos(location.getX(), location.getY(), location.getZ()); + delegate.world.spawnEntity(entity); + return new FabricEntity(entity); + } + + @Override + public int getMinHeight() { + return 0; } @Override @@ -95,7 +103,12 @@ public class FabricWorld implements World { return null; } - private static final class Handle { + @Override + public WorldAccess getWorld() { + return delegate.getWorld(); + } + + public static final class Handle { private final ServerWorld world; private final ChunkGenerator generator; @@ -103,5 +116,13 @@ public class FabricWorld implements World { this.world = world; this.generator = generator; } + + public ChunkGenerator getGenerator() { + return generator; + } + + public ServerWorld getWorld() { + return world; + } } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricSeededWorldAccess.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricSeededWorldAccess.java index 0f3c386d2..05b1dbb1e 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricSeededWorldAccess.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricSeededWorldAccess.java @@ -7,15 +7,19 @@ import com.dfsek.terra.api.platform.entity.EntityType; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; +import com.dfsek.terra.fabric.world.FabricAdapter; import com.dfsek.terra.fabric.world.block.FabricBlock; +import com.dfsek.terra.fabric.world.entity.FabricEntity; import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator; +import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.ServerWorldAccess; import net.minecraft.world.WorldAccess; import java.io.File; import java.util.UUID; -public class FabricSeededWorldAccess implements World { +public class FabricSeededWorldAccess implements World, FabricWorldHandle { private final Handle handle; @@ -70,23 +74,27 @@ public class FabricSeededWorldAccess implements World { } @Override - public Block getBlockAt(Location l) { - return getBlockAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()); + public Entity spawnEntity(Location location, EntityType entityType) { + net.minecraft.entity.Entity entity = FabricAdapter.adapt(entityType).create((ServerWorld) handle.worldAccess); + entity.setPos(location.getX(), location.getY(), location.getZ()); + handle.worldAccess.spawnEntity(entity); + return new FabricEntity(entity); } @Override - public Entity spawnEntity(Location location, EntityType entityType) { - return null; + public int getMinHeight() { + return 0; } @Override public int hashCode() { - return handle.worldAccess.hashCode(); + return ((ServerWorldAccess) handle.worldAccess).toServerWorld().hashCode(); } @Override public boolean equals(Object obj) { - return super.equals(obj); + if(!(obj instanceof FabricSeededWorldAccess)) return false; + return ((ServerWorldAccess) ((FabricSeededWorldAccess) obj).handle.worldAccess).toServerWorld().equals(((ServerWorldAccess) handle.worldAccess).toServerWorld()); } @Override @@ -94,6 +102,11 @@ public class FabricSeededWorldAccess implements World { return handle; } + @Override + public WorldAccess getWorld() { + return handle.worldAccess; + } + public static class Handle { private final WorldAccess worldAccess; private final long seed; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldAccess.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldAccess.java index 29d4c3fc2..8cb464353 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldAccess.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldAccess.java @@ -7,7 +7,9 @@ import com.dfsek.terra.api.platform.entity.EntityType; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; +import com.dfsek.terra.fabric.world.FabricAdapter; import com.dfsek.terra.fabric.world.block.FabricBlock; +import com.dfsek.terra.fabric.world.entity.FabricEntity; import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator; import net.minecraft.util.math.BlockPos; import net.minecraft.world.ServerWorldAccess; @@ -17,7 +19,7 @@ import net.minecraft.world.WorldAccess; import java.io.File; import java.util.UUID; -public class FabricWorldAccess implements World { +public class FabricWorldAccess implements World, FabricWorldHandle { private final WorldAccess delegate; public FabricWorldAccess(WorldAccess delegate) { @@ -71,17 +73,36 @@ public class FabricWorldAccess implements World { } @Override - public Block getBlockAt(Location l) { - return getBlockAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()); + public Entity spawnEntity(Location location, EntityType entityType) { + net.minecraft.entity.Entity entity = FabricAdapter.adapt(entityType).create(((ServerWorldAccess) delegate).toServerWorld()); + entity.setPos(location.getX(), location.getY(), location.getZ()); + delegate.spawnEntity(entity); + return new FabricEntity(entity); } @Override - public Entity spawnEntity(Location location, EntityType entityType) { - return null; + public int getMinHeight() { + return 0; } @Override public WorldAccess getHandle() { return delegate; } + + @Override + public WorldAccess getWorld() { + return delegate; + } + + @Override + public int hashCode() { + return ((ServerWorldAccess) delegate).toServerWorld().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof FabricWorldAccess)) return false; + return ((ServerWorldAccess) ((FabricWorldAccess) obj).delegate).toServerWorld().equals(((ServerWorldAccess) delegate).toServerWorld()); + } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldChunkRegion.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldChunkRegion.java deleted file mode 100644 index de898e032..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldChunkRegion.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.dfsek.terra.fabric.world.handles.world; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.entity.Entity; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; -import com.dfsek.terra.fabric.world.block.FabricBlock; -import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.ChunkRegion; - -import java.io.File; -import java.util.UUID; - -public class FabricWorldChunkRegion implements World { - private final Handle delegate; - - public FabricWorldChunkRegion(ChunkRegion delegate, net.minecraft.world.gen.chunk.ChunkGenerator generator) { - this.delegate = new Handle(delegate, generator); - } - - @Override - public long getSeed() { - return delegate.getChunk().getSeed(); - } - - @Override - public int getMaxHeight() { - return delegate.getChunk().getHeight(); - } - - @Override - public ChunkGenerator getGenerator() { - return new FabricChunkGenerator(delegate.getGenerator()); - } - - @Override - public String getName() { - return delegate.chunk.toString(); - } - - @Override - public UUID getUID() { - return UUID.randomUUID(); - } - - @Override - public boolean isChunkGenerated(int x, int z) { - return delegate.chunk.isChunkLoaded(x, z); - } - - @Override - public Chunk getChunkAt(int x, int z) { - return null; - } - - @Override - public File getWorldFolder() { - return null; - } - - @Override - public Block getBlockAt(int x, int y, int z) { - BlockPos pos = new BlockPos(x, y, z); - return new FabricBlock(pos, delegate.chunk); - } - - @Override - public int hashCode() { - return delegate.generator.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if(!(obj instanceof FabricWorldChunkRegion)) return false; - return ((FabricWorldChunkRegion) obj).delegate.generator.equals(delegate.generator); - } - - @Override - public Block getBlockAt(Location l) { - return getBlockAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()); - } - - @Override - public Entity spawnEntity(Location location, EntityType entityType) { - return null; - } - - @Override - public Object getHandle() { - return null; - } - - public static final class Handle { - private final ChunkRegion chunk; - private final net.minecraft.world.gen.chunk.ChunkGenerator generator; - - public Handle(ChunkRegion chunk, net.minecraft.world.gen.chunk.ChunkGenerator generator) { - this.chunk = chunk; - this.generator = generator; - } - - public net.minecraft.world.gen.chunk.ChunkGenerator getGenerator() { - return generator; - } - - public ChunkRegion getChunk() { - return chunk; - } - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldHandle.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldHandle.java new file mode 100644 index 000000000..7565201aa --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldHandle.java @@ -0,0 +1,7 @@ +package com.dfsek.terra.fabric.world.handles.world; + +import net.minecraft.world.WorldAccess; + +public interface FabricWorldHandle { + WorldAccess getWorld(); +} diff --git a/platforms/fabric/src/main/resources/terra-refmap.json b/platforms/fabric/src/main/resources/terra-refmap.json new file mode 100644 index 000000000..8dbf41449 --- /dev/null +++ b/platforms/fabric/src/main/resources/terra-refmap.json @@ -0,0 +1,16 @@ +{ + "mappings": { + "com/dfsek/terra/fabric/mixin/GeneratorTypeAccessor": { + "VALUES": "field_25052:Ljava/util/List;", + "translationKey": "field_25060:Lnet/minecraft/class_2561;" + } + }, + "data": { + "named:intermediary": { + "com/dfsek/terra/fabric/mixin/GeneratorTypeAccessor": { + "VALUES": "field_25052:Ljava/util/List;", + "translationKey": "field_25060:Lnet/minecraft/class_2561;" + } + } + } +} \ No newline at end of file diff --git a/platforms/fabric/src/main/resources/terra.accesswidener b/platforms/fabric/src/main/resources/terra.accesswidener index edfa21bd4..fcf59a730 100644 --- a/platforms/fabric/src/main/resources/terra.accesswidener +++ b/platforms/fabric/src/main/resources/terra.accesswidener @@ -3,4 +3,17 @@ accessWidener v1 named extendable method net/minecraft/client/world/GeneratorType (Ljava/lang/String;)V accessible field net/minecraft/server/world/ServerWorld worldProperties Lnet/minecraft/world/level/ServerWorldProperties; -mutable field net/minecraft/server/world/ServerWorld worldProperties Lnet/minecraft/world/level/ServerWorldProperties; \ No newline at end of file + +accessible method net/minecraft/world/MobSpawnerLogic getEntityId ()Lnet/minecraft/util/Identifier; + +accessible field net/minecraft/state/State PROPERTY_MAP_PRINTER Ljava/util/function/Function; + + +accessible field net/minecraft/world/biome/BiomeEffects fogColor I +accessible field net/minecraft/world/biome/BiomeEffects waterColor I +accessible field net/minecraft/world/biome/BiomeEffects waterFogColor I +accessible field net/minecraft/world/biome/BiomeEffects skyColor I + +accessible field net/minecraft/world/biome/BiomeEffects foliageColor Ljava/util/Optional; +accessible field net/minecraft/world/biome/BiomeEffects grassColor Ljava/util/Optional; +accessible field net/minecraft/world/biome/BiomeEffects grassColorModifier Lnet/minecraft/world/biome/BiomeEffects$GrassColorModifier; diff --git a/platforms/fabric/src/main/resources/terra.mixins.json b/platforms/fabric/src/main/resources/terra.mixins.json index a6b050657..8537843c7 100644 --- a/platforms/fabric/src/main/resources/terra.mixins.json +++ b/platforms/fabric/src/main/resources/terra.mixins.json @@ -3,12 +3,14 @@ "minVersion": "0.8", "package": "com.dfsek.terra.fabric.mixin", "compatibilityLevel": "JAVA_8", - "mixins": [], + "mixins": [ + ], "client": [ "GeneratorTypeAccessor" ], "server": [], "injectors": { "defaultRequire": 1 - } + }, + "refmap": "terra-refmap.json" } \ No newline at end of file diff --git a/platforms/region/src/main/java/com/dfsek/terra/StandalonePlugin.java b/platforms/region/src/main/java/com/dfsek/terra/StandalonePlugin.java index c933025c0..a1dd2e4c9 100644 --- a/platforms/region/src/main/java/com/dfsek/terra/StandalonePlugin.java +++ b/platforms/region/src/main/java/com/dfsek/terra/StandalonePlugin.java @@ -1,23 +1,28 @@ package com.dfsek.terra; import com.dfsek.tectonic.loading.TypeRegistry; -import com.dfsek.terra.api.core.TerraPlugin; -import com.dfsek.terra.api.core.event.EventManager; -import com.dfsek.terra.api.core.event.TerraEventManager; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.addons.TerraAddon; +import com.dfsek.terra.api.event.EventManager; +import com.dfsek.terra.api.event.TerraEventManager; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; import com.dfsek.terra.api.platform.handle.ItemHandle; import com.dfsek.terra.api.platform.handle.WorldHandle; import com.dfsek.terra.api.platform.world.Biome; import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.registry.LockedRegistry; +import com.dfsek.terra.api.util.logging.DebugLogger; +import com.dfsek.terra.api.util.logging.JavaLogger; import com.dfsek.terra.config.GenericLoaders; import com.dfsek.terra.config.PluginConfig; import com.dfsek.terra.config.lang.LangUtil; import com.dfsek.terra.config.lang.Language; -import com.dfsek.terra.debug.DebugLogger; +import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.platform.RawBiome; import com.dfsek.terra.platform.RawWorldHandle; -import com.dfsek.terra.registry.ConfigRegistry; +import com.dfsek.terra.registry.master.AddonRegistry; +import com.dfsek.terra.registry.master.ConfigRegistry; import com.dfsek.terra.world.TerraWorld; import java.io.File; @@ -26,6 +31,10 @@ import java.util.logging.Logger; public class StandalonePlugin implements TerraPlugin { private final ConfigRegistry registry = new ConfigRegistry(); + private final AddonRegistry addonRegistry = new AddonRegistry(this); + + private final LockedRegistry addonLockedRegistry = new LockedRegistry<>(addonRegistry); + private final PluginConfig config = new PluginConfig(); private final RawWorldHandle worldHandle = new RawWorldHandle(); private final EventManager eventManager = new TerraEventManager(this); @@ -35,19 +44,14 @@ public class StandalonePlugin implements TerraPlugin { return worldHandle; } - @Override - public boolean isEnabled() { - return true; - } - @Override public TerraWorld getWorld(World world) { return new TerraWorld(world, registry.get("DEFAULT"), this); } @Override - public Logger getLogger() { - return Logger.getLogger("Terra"); + public com.dfsek.terra.api.util.logging.Logger logger() { + return new JavaLogger(Logger.getLogger("Terra")); } @Override @@ -75,12 +79,17 @@ public class StandalonePlugin implements TerraPlugin { } @Override - public ConfigRegistry getRegistry() { - return registry; + public CheckedRegistry getConfigRegistry() { + return new CheckedRegistry<>(registry); } @Override - public void reload() { + public LockedRegistry getAddons() { + return addonLockedRegistry; + } + + @Override + public boolean reload() { throw new UnsupportedOperationException(); } @@ -101,15 +110,30 @@ public class StandalonePlugin implements TerraPlugin { @Override public DebugLogger getDebugLogger() { - return new DebugLogger(Logger.getLogger("Terra")); + Logger logger = Logger.getLogger("Terra"); + return new DebugLogger(new com.dfsek.terra.api.util.logging.Logger() { + @Override + public void info(String message) { + logger.info(message); + } + + @Override + public void warning(String message) { + logger.warning(message); + } + + @Override + public void severe(String message) { + logger.severe(message); + } + }); } @Override public void register(TypeRegistry registry) { registry .registerLoader(BlockData.class, (t, o, l) -> worldHandle.createBlockData((String) o)) - .registerLoader(Biome.class, (t, o, l) -> new RawBiome(o.toString())) - .registerLoader(MaterialData.class, (t, o, l) -> worldHandle.createMaterialData((String) o)); + .registerLoader(Biome.class, (t, o, l) -> new RawBiome(o.toString())); new GenericLoaders(this).register(registry); } diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/Data.java b/platforms/region/src/main/java/com/dfsek/terra/platform/Data.java index 0ba30f150..f1c845ab0 100644 --- a/platforms/region/src/main/java/com/dfsek/terra/platform/Data.java +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/Data.java @@ -1,10 +1,10 @@ package com.dfsek.terra.platform; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.block.BlockType; import net.querz.nbt.tag.CompoundTag; -public class Data implements BlockData, MaterialData { +public class Data implements BlockData, BlockType { private final CompoundTag data; private final String noProp; @@ -38,39 +38,25 @@ public class Data implements BlockData, MaterialData { @Override - public MaterialData getMaterial() { + public BlockType getBlockType() { return this; } - @Override - public boolean matches(MaterialData materialData) { - return ((Data) materialData).noProp.equals(noProp); - } - @Override public boolean matches(BlockData other) { return ((Data) other).noProp.equals(noProp); } - @Override - public boolean isSolid() { - return !isAir(); //TODO: actual implementation - } - @Override public boolean isAir() { return noProp.equals("minecraft:air"); } @Override - public double getMaxDurability() { - return 0; + public boolean isStructureVoid() { + return false; } - @Override - public BlockData createBlockData() { - return this; - } @Override public BlockData clone() { @@ -101,4 +87,14 @@ public class Data implements BlockData, MaterialData { if(!(obj instanceof Data)) return false; return ((Data) obj).noProp.equals(noProp); } + + @Override + public BlockData getDefaultData() { + return this; + } + + @Override + public boolean isSolid() { + return false; + } } diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectBlock.java b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectBlock.java index 55372978b..3169d0667 100644 --- a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectBlock.java +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectBlock.java @@ -5,7 +5,7 @@ import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.block.BlockType; import com.dfsek.terra.api.platform.block.state.BlockState; import net.jafama.FastMath; @@ -56,7 +56,7 @@ public class DirectBlock implements Block { } @Override - public MaterialData getType() { + public BlockType getType() { return new Data(world.getData(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ())); } diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectChunkData.java b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectChunkData.java index 2705e70e2..4eac21cce 100644 --- a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectChunkData.java +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectChunkData.java @@ -4,12 +4,12 @@ import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.generator.ChunkData; import net.querz.mca.Chunk; import net.querz.nbt.tag.CompoundTag; import org.jetbrains.annotations.NotNull; -public class DirectChunkData implements ChunkGenerator.ChunkData, com.dfsek.terra.api.platform.world.Chunk { +public class DirectChunkData implements ChunkData, com.dfsek.terra.api.platform.world.Chunk { private final Chunk delegate; private final DirectWorld world; private final int x; diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectWorld.java b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectWorld.java index c27f47abf..3aacfabb9 100644 --- a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectWorld.java +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectWorld.java @@ -83,13 +83,13 @@ public class DirectWorld implements World { } @Override - public Block getBlockAt(Location l) { - return getBlockAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()); + public Entity spawnEntity(Location location, EntityType entityType) { + return null; } @Override - public Entity spawnEntity(Location location, EntityType entityType) { - return null; + public int getMinHeight() { + return 0; } @Override diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/GenWrapper.java b/platforms/region/src/main/java/com/dfsek/terra/platform/GenWrapper.java index 25118e8bf..7de56d5bf 100644 --- a/platforms/region/src/main/java/com/dfsek/terra/platform/GenWrapper.java +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/GenWrapper.java @@ -1,22 +1,12 @@ package com.dfsek.terra.platform; -import com.dfsek.terra.api.platform.world.BiomeGrid; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.BlockPopulator; import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import com.dfsek.terra.world.generation.MasterChunkGenerator; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collections; -import java.util.List; -import java.util.Random; +import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D; public class GenWrapper implements ChunkGenerator { - private final MasterChunkGenerator generator; + private final DefaultChunkGenerator3D generator; - public GenWrapper(MasterChunkGenerator generator) { + public GenWrapper(DefaultChunkGenerator3D generator) { this.generator = generator; } @@ -25,43 +15,4 @@ public class GenWrapper implements ChunkGenerator { return generator; } - @Override - public boolean isParallelCapable() { - return true; - } - - @Override - public boolean shouldGenerateCaves() { - return true; - } - - @Override - public boolean shouldGenerateDecorations() { - return true; - } - - @Override - public boolean shouldGenerateMobs() { - return true; - } - - @Override - public boolean shouldGenerateStructures() { - return true; - } - - @Override - public ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome) { - throw new UnsupportedOperationException(); // gen is directly handled by Generator - } - - @Override - public List getDefaultPopulators(World world) { - return Collections.emptyList(); - } - - @Override - public @Nullable TerraChunkGenerator getTerraGenerator() { - return generator; - } } diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/RawTree.java b/platforms/region/src/main/java/com/dfsek/terra/platform/RawTree.java index 867e1bd4a..b58efb7e0 100644 --- a/platforms/region/src/main/java/com/dfsek/terra/platform/RawTree.java +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/RawTree.java @@ -1,12 +1,10 @@ package com.dfsek.terra.platform; import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.world.tree.Tree; -import java.util.Collections; import java.util.Random; -import java.util.Set; public class RawTree implements Tree { // TODO: implement @Override @@ -15,7 +13,7 @@ public class RawTree implements Tree { // TODO: implement } @Override - public Set getSpawnable() { - return Collections.emptySet(); + public MaterialSet getSpawnable() { + return MaterialSet.empty(); } } diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/RawWorldHandle.java b/platforms/region/src/main/java/com/dfsek/terra/platform/RawWorldHandle.java index a6c487aa7..2e2ce5b63 100644 --- a/platforms/region/src/main/java/com/dfsek/terra/platform/RawWorldHandle.java +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/RawWorldHandle.java @@ -1,37 +1,16 @@ package com.dfsek.terra.platform; -import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.MaterialData; import com.dfsek.terra.api.platform.entity.EntityType; import com.dfsek.terra.api.platform.handle.WorldHandle; public class RawWorldHandle implements WorldHandle { - @Override - public void setBlockData(Block block, BlockData data, boolean physics) { - - } - - @Override - public BlockData getBlockData(Block block) { - return null; - } - - @Override - public MaterialData getType(Block block) { - return null; - } @Override public BlockData createBlockData(String data) { return new Data(data); } - @Override - public MaterialData createMaterialData(String data) { - return new Data(data); - } - @Override public EntityType getEntity(String id) { return null; diff --git a/platforms/region/src/main/java/com/dfsek/terra/region/Generator.java b/platforms/region/src/main/java/com/dfsek/terra/region/Generator.java index 4f425e224..cd6a55e66 100644 --- a/platforms/region/src/main/java/com/dfsek/terra/region/Generator.java +++ b/platforms/region/src/main/java/com/dfsek/terra/region/Generator.java @@ -1,10 +1,11 @@ package com.dfsek.terra.region; import com.dfsek.terra.StandalonePlugin; +import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.platform.DirectChunkData; import com.dfsek.terra.platform.DirectWorld; import com.dfsek.terra.platform.GenWrapper; -import com.dfsek.terra.world.generation.MasterChunkGenerator; +import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D; import com.dfsek.terra.world.generation.math.SamplerCache; import com.dfsek.terra.world.population.FloraPopulator; import com.dfsek.terra.world.population.OrePopulator; @@ -23,7 +24,7 @@ public class Generator { StructurePopulator structurePopulator; TreePopulator treePopulator; OrePopulator orePopulator; - MasterChunkGenerator generator; + DefaultChunkGenerator3D generator; public Generator(long seed, StandalonePlugin plugin) { plugin.load(); @@ -31,7 +32,7 @@ public class Generator { structurePopulator = new StructurePopulator(plugin); treePopulator = new TreePopulator(plugin); orePopulator = new OrePopulator(plugin); - generator = new MasterChunkGenerator(plugin.getRegistry().get("DEFAULT"), plugin, new SamplerCache(plugin)); + generator = new DefaultChunkGenerator3D(plugin.getConfigRegistry().get("DEFAULT"), plugin); this.seed = seed; } diff --git a/platforms/sponge/build.gradle.kts b/platforms/sponge/build.gradle.kts new file mode 100644 index 000000000..9880b8c93 --- /dev/null +++ b/platforms/sponge/build.gradle.kts @@ -0,0 +1,28 @@ +import com.dfsek.terra.configureCommon + +plugins { + java + id("org.spongepowered.plugin").version("0.9.0") +} + +configureCommon() + +group = "com.dfsek.terra" + +repositories { + mavenCentral() + jcenter() +} + +dependencies { + "compileOnly"("org.spongepowered:spongeapi:7.2.0") + "shadedApi"(project(":common")) + "shadedImplementation"("org.yaml:snakeyaml:1.27") + "shadedImplementation"("com.googlecode.json-simple:json-simple:1.1.1") +} + +sponge { + plugin { + id = "terra" + } +} \ No newline at end of file diff --git a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/SpongeAdapter.java b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/SpongeAdapter.java new file mode 100644 index 000000000..781b5f91e --- /dev/null +++ b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/SpongeAdapter.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.sponge; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.sponge.world.block.data.SpongeBlockData; +import org.spongepowered.api.block.BlockState; + +public final class SpongeAdapter { + public static BlockData adapt(BlockState state) { + return new SpongeBlockData(state); + } + + public static BlockState adapt(BlockData data) { + return ((SpongeBlockData) data).getHandle(); + } +} diff --git a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/SpongeLogger.java b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/SpongeLogger.java new file mode 100644 index 000000000..1ead85e8d --- /dev/null +++ b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/SpongeLogger.java @@ -0,0 +1,26 @@ +package com.dfsek.terra.sponge; + +import com.dfsek.terra.api.util.logging.Logger; + +public class SpongeLogger implements Logger { + private final org.slf4j.Logger logger; + + public SpongeLogger(org.slf4j.Logger logger) { + this.logger = logger; + } + + @Override + public void info(String message) { + logger.info(message); + } + + @Override + public void warning(String message) { + logger.warn(message); + } + + @Override + public void severe(String message) { + logger.error(message); + } +} diff --git a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/TerraSpongePlugin.java b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/TerraSpongePlugin.java new file mode 100644 index 000000000..78baf45d5 --- /dev/null +++ b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/TerraSpongePlugin.java @@ -0,0 +1,141 @@ +package com.dfsek.terra.sponge; + +import com.dfsek.tectonic.loading.TypeRegistry; +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.addons.TerraAddon; +import com.dfsek.terra.api.event.EventManager; +import com.dfsek.terra.api.event.TerraEventManager; +import com.dfsek.terra.api.platform.handle.ItemHandle; +import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.registry.LockedRegistry; +import com.dfsek.terra.api.util.logging.DebugLogger; +import com.dfsek.terra.config.PluginConfig; +import com.dfsek.terra.config.lang.Language; +import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.registry.master.AddonRegistry; +import com.dfsek.terra.registry.master.ConfigRegistry; +import com.dfsek.terra.sponge.world.SpongeWorldHandle; +import com.dfsek.terra.world.TerraWorld; +import com.google.inject.Inject; +import org.slf4j.Logger; +import org.spongepowered.api.config.ConfigDir; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.game.state.GameStartedServerEvent; +import org.spongepowered.api.plugin.Plugin; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; + +@Plugin(id = "terra", name = "Terra-Sponge", version = "", description = "Terra") +public class TerraSpongePlugin implements TerraPlugin { + private final ConfigRegistry configRegistry = new ConfigRegistry(); + private final CheckedRegistry packCheckedRegistry = new CheckedRegistry<>(configRegistry); + private final PluginConfig config = new PluginConfig(); + private final AddonRegistry addonRegistry = new AddonRegistry(this); + private final LockedRegistry addonLockedRegistry = new LockedRegistry<>(addonRegistry); + + private final SpongeWorldHandle spongeWorldHandle = new SpongeWorldHandle(); + + private final EventManager eventManager = new TerraEventManager(this); + + @Inject + @ConfigDir(sharedRoot = false) + private Path privateConfigDir; + + @Inject + private Logger logger; + + + @Listener + public void initialize(GameStartedServerEvent event) { + addonRegistry.loadAll(); + configRegistry.loadAll(this); + } + + @Override + public void register(TypeRegistry registry) { + + } + + @Override + public WorldHandle getWorldHandle() { + return spongeWorldHandle; + } + + @Override + public TerraWorld getWorld(World world) { + return null; + } + + @Override + public com.dfsek.terra.api.util.logging.Logger logger() { + return new SpongeLogger(logger); + } + + @Override + public PluginConfig getTerraConfig() { + return config; + } + + @Override + public File getDataFolder() { + return privateConfigDir.toFile(); + } + + @Override + public boolean isDebug() { + return true; + } + + @Override + public Language getLanguage() { + try { + return new Language(new File(getDataFolder(), "lang/en_us.yml")); + } catch(IOException e) { + throw new IllegalArgumentException(); + } + } + + @Override + public CheckedRegistry getConfigRegistry() { + return packCheckedRegistry; + } + + @Override + public LockedRegistry getAddons() { + return addonLockedRegistry; + } + + @Override + public boolean reload() { + return false; + } + + @Override + public ItemHandle getItemHandle() { + return null; + } + + @Override + public void saveDefaultConfig() { + + } + + @Override + public String platformName() { + return "Sponge"; + } + + @Override + public DebugLogger getDebugLogger() { + return null; + } + + @Override + public EventManager getEventManager() { + return eventManager; + } +} diff --git a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/world/SpongeWorldHandle.java b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/world/SpongeWorldHandle.java new file mode 100644 index 000000000..422229ba9 --- /dev/null +++ b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/world/SpongeWorldHandle.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.sponge.world; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.entity.EntityType; +import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.sponge.SpongeAdapter; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.block.BlockState; + +public class SpongeWorldHandle implements WorldHandle { + @Override + public BlockData createBlockData(String data) { + return SpongeAdapter.adapt(Sponge.getRegistry().getType(BlockState.class, data).orElseThrow(() -> new IllegalArgumentException("Invalid block data \"" + data + "\""))); + } + + @Override + public EntityType getEntity(String id) { + return null; + } +} diff --git a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/world/block/data/SpongeBlockData.java b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/world/block/data/SpongeBlockData.java new file mode 100644 index 000000000..eb68b9030 --- /dev/null +++ b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/world/block/data/SpongeBlockData.java @@ -0,0 +1,48 @@ +package com.dfsek.terra.sponge.world.block.data; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockType; +import org.spongepowered.api.block.BlockState; + +public class SpongeBlockData implements BlockData { + private final BlockState delegate; + + public SpongeBlockData(BlockState delegate) { + this.delegate = delegate; + } + + @Override + public BlockState getHandle() { + return delegate; + } + + @Override + public BlockType getBlockType() { + return null; + } + + @Override + public boolean matches(BlockData other) { + return false; + } + + @Override + public BlockData clone() { + return null; + } + + @Override + public String getAsString() { + return null; + } + + @Override + public boolean isAir() { + return false; + } + + @Override + public boolean isStructureVoid() { + return false; + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 682f7912b..303d70045 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -12,6 +12,7 @@ include("common") include("platforms:bukkit") include("platforms:fabric") include("platforms:region") +include("platforms:sponge") pluginManagement { repositories {