diff --git a/.editorconfig b/.editorconfig index 8fbad9dcd..1c53c29c2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -342,6 +342,6 @@ ij_json_wrap_long_lines = false indent_size = 2 ij_yaml_keep_indents_on_empty_lines = true ij_yaml_keep_line_breaks = true -ij_yaml_space_before_colon = true +ij_yaml_space_before_colon = false ij_yaml_spaces_within_braces = true ij_yaml_spaces_within_brackets = true diff --git a/README.md b/README.md index 45629f0eb..8986ce6b7 100644 --- a/README.md +++ b/README.md @@ -7,20 +7,36 @@ to your specifications, with no knowledge of Java required. * 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) +* Forge: [Modrinth](https://modrinth.com/mod/terra) / [CurseForge](https://www.curseforge.com/minecraft/mc-mods/terra-world-generator) -## Building and running Terra +## Building and Running Terra -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. +To build, simply run `./gradlew build` (`gradlew.bat build` on Windows). This will build all platforms, and +produce JARs in `platforms//build/libs` -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) -and install the server in the `target/server` directory, along with all the needed plugins. +### Production JARs: +* Bukkit: `Terra--shaded.jar` +* Fabric: `Terra--shaded-mapped.jar` +* Forge: `Terra--shaded.jar` -**Note: You will need to adjust the `NAME` variable `bukkit.yml` of the test server if you are not using the default Terra config.** +### Building a Specific Platform +To build a specific platform, run `gradlew :platforms::build`. +JARs are produced in `platforms//build/libs`. + +### Running Minecraft in the IDE +To run Minecraft with Terra in the IDE (for testing) use the following tasks: +* Bukkit + * `installPaper` - Install a [Paper](https://github.com/PaperMC/Paper) test server. (Only needs to be run once). + * `installPurpur` - Install a [Purpur](https://github.com/pl3xgaming/Purpur) test server. (Only needs to be run once). + * `runPaper` - Run the Paper test server with Terra (`installPaper` must have been run previously). + * `runPurpur` - Run the Purpur test server with Terra (`installPurpur` must have been run previously). +* Fabric + * `runClient` - Run a Minecraft client with Terra installed. + * `runServer` - Run a Minecraft server with Terra installed. +* Forge + * `runClient` - Run a Minecraft client with Terra installed. + * `runServer` - Run a Minecraft server with Terra installed. ## Contributing Contributions are welcome! If you want to see a feature in Terra, please, open an issue, or implement it yourself and submit a PR! diff --git a/build.gradle.kts b/build.gradle.kts index b544506a5..6b9bb6e74 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,6 +5,23 @@ val versionObj = Version("6", "0", "0", true) allprojects { version = versionObj group = "com.dfsek.terra" + + tasks.withType().configureEach { + options.isFork = true + options.isIncremental = true + } + tasks.withType().configureEach { + useJUnitPlatform() + + maxHeapSize = "2G" + ignoreFailures = false + failFast = true + maxParallelForks = (Runtime.getRuntime().availableProcessors() - 1).takeIf { it > 0 } ?: 1 + + reports.html.isEnabled = false + reports.junitXml.isEnabled = false + } + } /** * Version class that does version stuff. diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/CommonConfig.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/CommonConfig.kt index c06a71b2d..3f10dc573 100644 --- a/buildSrc/src/main/kotlin/com/dfsek/terra/CommonConfig.kt +++ b/buildSrc/src/main/kotlin/com/dfsek/terra/CommonConfig.kt @@ -7,26 +7,11 @@ import org.gradle.kotlin.dsl.withType import java.io.ByteArrayOutputStream fun Project.configureCommon() { - apply(plugin = "java-library") - apply(plugin = "maven-publish") - apply(plugin = "idea") - configureDependencies() configureCompilation() configureDistribution() version = rootProject.version - - - - tasks.withType().configureEach { - useJUnitPlatform() - - maxHeapSize = "2G" - ignoreFailures = false - failFast = true - maxParallelForks = 12 - } } fun Project.getGitHash(): String { diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt index a6619cc1f..a8fc73b96 100644 --- a/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt +++ b/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt @@ -3,14 +3,16 @@ package com.dfsek.terra import org.gradle.api.JavaVersion import org.gradle.api.Project import org.gradle.api.plugins.JavaPluginConvention +import org.gradle.api.tasks.bundling.Jar 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.kotlin.dsl.* import org.gradle.language.jvm.tasks.ProcessResources fun Project.configureCompilation() { + apply(plugin = "maven-publish") + apply(plugin = "idea") + configure { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -19,7 +21,7 @@ fun Project.configureCompilation() { tasks.withType { options.encoding = "UTF-8" doFirst { - options.compilerArgs = mutableListOf("-Xlint:all") + options.compilerArgs.add("-Xlint:all") } } @@ -35,4 +37,19 @@ fun Project.configureCompilation() { tasks.withType { options.encoding = "UTF-8" } + + tasks.withType { + archiveBaseName.set("Terra-${archiveBaseName.get()}") + from("../LICENSE", "../../LICENSE") + } + + tasks.register("sourcesJar") { + archiveClassifier.set("sources") + } + + tasks.register("javadocJar") { + dependsOn("javadoc") + archiveClassifier.set("javadoc") + from(tasks.getByName("javadoc").destinationDir) + } } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/DependencyConfig.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/DependencyConfig.kt index 4bab053e4..a73154b3f 100644 --- a/buildSrc/src/main/kotlin/com/dfsek/terra/DependencyConfig.kt +++ b/buildSrc/src/main/kotlin/com/dfsek/terra/DependencyConfig.kt @@ -1,13 +1,27 @@ package com.dfsek.terra import org.gradle.api.Project +import org.gradle.kotlin.dsl.apply import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.invoke import org.gradle.kotlin.dsl.repositories fun Project.configureDependencies() { + apply(plugin = "java") + apply(plugin = "java-library") + + configurations { + val shaded = create("shaded") + val shadedApi = create("shadedApi") + shaded.extendsFrom(shadedApi) + getByName("api").extendsFrom(shadedApi) + val shadedImplementation = create("shadedImplementation") + shaded.extendsFrom(shadedImplementation) + getByName("implementation").extendsFrom(shadedImplementation) + } repositories { - maven { url = uri("http://maven.enginehub.org/repo/") } + maven { url = uri("https://maven.enginehub.org/repo/") } maven { url = uri("https://repo.codemc.org/repository/maven-public") } maven { url = uri("https://papermc.io/repo/repository/maven-public/") } maven { url = uri("https://maven.fabricmc.net/") } @@ -19,6 +33,6 @@ fun Project.configureDependencies() { dependencies { "testImplementation"("org.junit.jupiter:junit-jupiter-api:5.7.0") "testImplementation"("org.junit.jupiter:junit-jupiter-engine:5.7.0") - "compileOnly"("org.jetbrains:annotations:20.1.0") + "api"("org.jetbrains:annotations:20.1.0") } } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/DistributionConfig.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/DistributionConfig.kt index c874d8820..ee81dc9b8 100644 --- a/buildSrc/src/main/kotlin/com/dfsek/terra/DistributionConfig.kt +++ b/buildSrc/src/main/kotlin/com/dfsek/terra/DistributionConfig.kt @@ -14,17 +14,6 @@ fun Project.configureDistribution() { apply(plugin = "java-library") apply(plugin = "com.github.johnrengelman.shadow") - configurations { - val shaded = create("shaded") - getByName("compile").extendsFrom(shaded) - val shadedApi = create("shadedApi") - shaded.extendsFrom(shadedApi) - getByName("api").extendsFrom(shadedApi) - val shadedImplementation = create("shadedImplementation") - shaded.extendsFrom(shadedImplementation) - getByName("implementation").extendsFrom(shadedImplementation) - } - val downloadDefaultPacks = tasks.create("downloadDefaultPacks") { group = "terra" doFirst { @@ -38,21 +27,6 @@ fun Project.configureDistribution() { } tasks["processResources"].dependsOn(downloadDefaultPacks) - tasks.withType { - archiveBaseName.set("Terra-${archiveBaseName.get()}") - from("../LICENSE", "../../LICENSE") - } - - tasks.register("sourcesJar") { - archiveClassifier.set("sources") - } - - tasks.register("javadocJar") { - dependsOn("javadoc") - archiveClassifier.set("javadoc") - from(tasks.getByName("javadoc").destinationDir) - } - tasks.named("shadowJar") { // Tell shadow to download the packs dependsOn(downloadDefaultPacks) diff --git a/common/build.gradle.kts b/common/build.gradle.kts index ef4e40978..311054dd7 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -1,11 +1,14 @@ -import com.dfsek.terra.configureCommon +import com.dfsek.terra.configureCompilation +import com.dfsek.terra.configureDependencies plugins { `java-library` `maven-publish` + idea } -configureCommon() +configureCompilation() +configureDependencies() group = "com.dfsek.terra.common" diff --git a/common/src/main/java/com/dfsek/terra/api/TerraPlugin.java b/common/src/main/java/com/dfsek/terra/api/TerraPlugin.java index 679139663..1fa8de87e 100644 --- a/common/src/main/java/com/dfsek/terra/api/TerraPlugin.java +++ b/common/src/main/java/com/dfsek/terra/api/TerraPlugin.java @@ -7,6 +7,7 @@ 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.JarUtil; import com.dfsek.terra.api.util.logging.DebugLogger; import com.dfsek.terra.api.util.logging.Logger; import com.dfsek.terra.config.PluginConfig; @@ -16,6 +17,9 @@ import com.dfsek.terra.profiler.Profiler; import com.dfsek.terra.world.TerraWorld; import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.jar.JarFile; /** * Represents a Terra mod/plugin instance. @@ -65,4 +69,8 @@ public interface TerraPlugin extends LoaderRegistrar { } Profiler getProfiler(); + + default JarFile getModJar() throws URISyntaxException, IOException { + return JarUtil.getJarFile(); + } } 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 index e58bd236f..57b434164 100644 --- a/common/src/main/java/com/dfsek/terra/api/command/TerraCommandManager.java +++ b/common/src/main/java/com/dfsek/terra/api/command/TerraCommandManager.java @@ -65,7 +65,7 @@ public class TerraCommandManager implements CommandManager { return; } - if(commandClass.isAnnotationPresent(WorldCommand.class) && (!(sender instanceof Player) || !TerraWorld.isTerraWorld(((Player) sender).getWorld()))) { + if(commandClass.isAnnotationPresent(WorldCommand.class) && (!(sender instanceof Player) || !(((Player) sender).getWorld()).isTerraWorld())) { sender.sendMessage("Command must be executed in a Terra world."); return; } 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 dfa8d9719..5b7ac6906 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,6 +1,7 @@ package com.dfsek.terra.api.platform.inventory; import com.dfsek.terra.api.platform.Handle; +import com.dfsek.terra.api.platform.inventory.item.Damageable; import com.dfsek.terra.api.platform.inventory.item.ItemMeta; public interface ItemStack extends Handle { @@ -13,4 +14,8 @@ public interface ItemStack extends Handle { ItemMeta getItemMeta(); void setItemMeta(ItemMeta meta); + + default boolean isDamageable() { + return getItemMeta() instanceof Damageable; + } } 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 1dbcd85a6..45d13ab4d 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 @@ -6,6 +6,8 @@ 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.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; +import com.dfsek.terra.api.world.generation.TerraChunkGenerator; import java.io.File; import java.util.UUID; @@ -17,20 +19,12 @@ public interface World extends Handle { ChunkGenerator getGenerator(); - String getName(); - - UUID getUID(); - - boolean isChunkGenerated(int x, int z); - 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); default Block getBlockAt(Location l) { @@ -40,4 +34,12 @@ public interface World extends Handle { Entity spawnEntity(Location location, EntityType entityType); int getMinHeight(); + + default boolean isTerraWorld() { + return getGenerator().getHandle() instanceof GeneratorWrapper; + } + + default TerraChunkGenerator getTerraGenerator() { + return ((GeneratorWrapper) getGenerator().getHandle()).getHandle(); + } } 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 189a0c100..517777db0 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 @@ -34,8 +34,8 @@ public class DamageFunction implements LootFunction { @Override public ItemStack apply(ItemStack original, Random r) { if(original == null) return null; + if(!original.isDamageable()) return original; ItemMeta meta = original.getItemMeta(); - if(!(meta instanceof Damageable)) return original; double itemDurability = (r.nextDouble() * (max - min)) + min; Damageable damage = (Damageable) meta; damage.setDamage((int) (original.getType().getMaxDurability() - (itemDurability / 100) * original.getType().getMaxDurability())); 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 6b0e9de19..43c80e7f9 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 @@ -33,6 +33,9 @@ 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.profiler.ProfileFrame; +import com.dfsek.terra.registry.config.FunctionRegistry; +import com.dfsek.terra.registry.config.LootRegistry; +import com.dfsek.terra.registry.config.ScriptRegistry; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import net.jafama.FastMath; @@ -89,6 +92,12 @@ public class StructureScript { .registerFunction("ceil", new UnaryNumberFunctionBuilder(number -> FastMath.ceil(number.doubleValue()))) .registerFunction("log", new UnaryNumberFunctionBuilder(number -> FastMath.log(number.doubleValue()))) .registerFunction("round", new UnaryNumberFunctionBuilder(number -> FastMath.round(number.doubleValue()))) + .registerFunction("sin", new UnaryNumberFunctionBuilder(number -> FastMath.sin(number.doubleValue()))) + .registerFunction("cos", new UnaryNumberFunctionBuilder(number -> FastMath.cos(number.doubleValue()))) + .registerFunction("tan", new UnaryNumberFunctionBuilder(number -> FastMath.tan(number.doubleValue()))) + .registerFunction("asin", new UnaryNumberFunctionBuilder(number -> FastMath.asin(number.doubleValue()))) + .registerFunction("acos", new UnaryNumberFunctionBuilder(number -> FastMath.acos(number.doubleValue()))) + .registerFunction("atan", new UnaryNumberFunctionBuilder(number -> FastMath.atan(number.doubleValue()))) .registerFunction("max", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.max(number.doubleValue(), number2.doubleValue()))) .registerFunction("min", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.min(number.doubleValue(), number2.doubleValue()))); diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedEntity.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedEntity.java index 6b8315ca2..fc90123ce 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedEntity.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedEntity.java @@ -19,6 +19,6 @@ public class BufferedEntity implements BufferedItem { @Override public void paste(Location origin) { Entity entity = origin.clone().add(0.5, 0, 0.5).getWorld().spawnEntity(origin, type); - main.getEventManager().callEvent(new EntitySpawnEvent(main.getWorld(entity.getWorld()).getGenerator().getConfigPack(), entity, entity.getLocation())); + main.getEventManager().callEvent(new EntitySpawnEvent(entity.getWorld().getTerraGenerator().getConfigPack(), entity, entity.getLocation())); } } 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 a2c474a08..89e534449 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 @@ -32,7 +32,7 @@ public class BufferedLootApplication implements BufferedItem { } Container container = (Container) data; - LootPopulateEvent event = new LootPopulateEvent(block, container, table, main.getWorld(block.getLocation().getWorld()).getGenerator().getConfigPack(), structure); + LootPopulateEvent event = new LootPopulateEvent(block, container, table, block.getLocation().getWorld().getTerraGenerator().getConfigPack(), structure); main.getEventManager().callEvent(event); if(event.isCancelled()) return; @@ -40,7 +40,7 @@ public class BufferedLootApplication implements BufferedItem { data.update(false); } catch(Exception e) { main.logger().warning("Could not apply loot at " + origin + ": " + e.getMessage()); - main.getDebugLogger().stack(e); + e.printStackTrace(); } } } 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 703ca2695..158f1a951 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 @@ -21,7 +21,7 @@ public class BufferedStateManipulator implements BufferedItem { state.update(false); } catch(Exception e) { main.logger().warning("Could not apply BlockState at " + origin + ": " + e.getMessage()); - main.getDebugLogger().stack(e); + e.printStackTrace(); } } } diff --git a/common/src/main/java/com/dfsek/terra/api/util/JarUtil.java b/common/src/main/java/com/dfsek/terra/api/util/JarUtil.java index 20ad875cc..981dfdb7f 100644 --- a/common/src/main/java/com/dfsek/terra/api/util/JarUtil.java +++ b/common/src/main/java/com/dfsek/terra/api/util/JarUtil.java @@ -1,9 +1,13 @@ package com.dfsek.terra.api.util; +import com.dfsek.terra.api.TerraPlugin; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.net.URISyntaxException; +import java.net.URL; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -32,4 +36,12 @@ public class JarUtil { } } } + + public static JarFile getJarFile() throws URISyntaxException, IOException { + return new JarFile(new File(getJarURL().toURI())); + } + + public static URL getJarURL() { + return TerraPlugin.class.getProtectionDomain().getCodeSource().getLocation(); + } } 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 4efba0ecc..46795525d 100644 --- a/common/src/main/java/com/dfsek/terra/config/PluginConfig.java +++ b/common/src/main/java/com/dfsek/terra/config/PluginConfig.java @@ -81,12 +81,12 @@ public class PluginConfig implements ConfigTemplate { ConfigLoader loader = new ConfigLoader(); loader.load(this, file); if(dumpDefaultConfig) { // Don't dump default config if already loaded. - try(JarFile jar = new JarFile(new File(TerraPlugin.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) { + try(JarFile jar = main.getModJar()) { JarUtil.copyResourcesToDirectory(jar, "packs", new File(main.getDataFolder(), "packs").toString()); } catch(IOException | URISyntaxException e) { main.getDebugLogger().error("Failed to dump default config files!"); e.printStackTrace(); - main.getDebugLogger().error("Report this to Terra!"); + main.getDebugLogger().error("Either you're on Forge, or this is a bug. If it's the latter, report this to Terra!"); } } } catch(ConfigException | IOException e) { 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 index 06cd712fc..26082be6a 100644 --- a/common/src/main/java/com/dfsek/terra/config/dummy/DummyWorld.java +++ b/common/src/main/java/com/dfsek/terra/config/dummy/DummyWorld.java @@ -9,9 +9,6 @@ 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() { @@ -33,31 +30,11 @@ public class DummyWorld implements World { 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"); diff --git a/common/src/main/java/com/dfsek/terra/config/fileloaders/Loader.java b/common/src/main/java/com/dfsek/terra/config/fileloaders/Loader.java index b6d2a4b8a..c4b0bf6c7 100644 --- a/common/src/main/java/com/dfsek/terra/config/fileloaders/Loader.java +++ b/common/src/main/java/com/dfsek/terra/config/fileloaders/Loader.java @@ -1,5 +1,6 @@ package com.dfsek.terra.config.fileloaders; +import com.dfsek.tectonic.config.Configuration; import com.dfsek.tectonic.exception.ConfigException; import com.dfsek.terra.api.util.GlueList; @@ -18,8 +19,12 @@ public abstract class Loader { * * @param consumer Something to do with the streams. */ - public Loader then(ExceptionalConsumer> consumer) throws ConfigException { - consumer.accept(new GlueList<>(streams.values())); + public Loader then(ExceptionalConsumer> consumer) throws ConfigException { + List list = new GlueList<>(); + streams.forEach((id, stream) -> { + list.add(new Configuration(stream, id)); + }); + consumer.accept(list); return this; } 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 347a1e577..87f24b13e 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 @@ -17,7 +17,7 @@ public final class LangUtil { public static void load(String langID, TerraPlugin main) { Logger logger = main.logger(); File file = new File(main.getDataFolder(), "lang"); - try(JarFile jar = new JarFile(new File(TerraPlugin.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) { + try(JarFile jar = main.getModJar()) { copyResourcesToDirectory(jar, "lang", file.toString()); } catch(IOException | URISyntaxException e) { main.getDebugLogger().error("Failed to dump language files!"); 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 07ea5b52a..f8d2775fc 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 @@ -193,6 +193,10 @@ public class ConfigPack implements LoaderRegistrar { registryMap.forEach((clazz, pair) -> pair.getLeft().getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in '" + clazz + "' registry: '" + id + "'"))); } + protected Map, ImmutablePair, CheckedRegistry>> getRegistryMap() { + return registryMap; + } + @SuppressWarnings({"unchecked", "rawtypes"}) private void load(long start, TerraPlugin main) throws ConfigException { main.getEventManager().callEvent(new ConfigPackPreLoadEvent(this)); 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 index 11f473efd..c3be03456 100644 --- a/common/src/main/java/com/dfsek/terra/config/pack/WorldConfig.java +++ b/common/src/main/java/com/dfsek/terra/config/pack/WorldConfig.java @@ -31,8 +31,7 @@ public class WorldConfig { this.pack = pack; this.samplerCache = new SamplerCache(main, world); - pack.getConfigTypeRegistry().forEach(configType -> registryMap.put(configType.getTypeClass(), new LockedRegistry<>(pack.getRegistry(configType.getTypeClass())))); - + pack.getRegistryMap().forEach((clazz, pair) -> registryMap.put(clazz, new LockedRegistry<>(pair.getLeft()))); OpenRegistry biomeOpenRegistry = new OpenRegistry<>(); pack.getRegistry(BiomeBuilder.class).forEach((id, biome) -> biomeOpenRegistry.add(id, biome.apply(world.getWorld().getSeed()))); diff --git a/common/src/main/java/com/dfsek/terra/profiler/Profiler.java b/common/src/main/java/com/dfsek/terra/profiler/Profiler.java index 226b8860e..65560ad56 100644 --- a/common/src/main/java/com/dfsek/terra/profiler/Profiler.java +++ b/common/src/main/java/com/dfsek/terra/profiler/Profiler.java @@ -3,22 +3,54 @@ package com.dfsek.terra.profiler; import java.util.Map; public interface Profiler { + /** + * Push a frame to this profiler. + * + * @param frame ID of frame. + */ void push(String frame); + /** + * Pop a frame from this profiler. + * + * @param frame ID of frame. Must match ID + * at the top of the profiler stack. + */ void pop(String frame); + /** + * Start profiling. + */ void start(); + /** + * Stop profiling. + */ void stop(); + /** + * Get the profiler data. + * + * @return Profiler data. + */ Map getTimings(); + /** + * Return a {@link AutoCloseable} implementation that + * may be used in a try-with-resources statement for + * more intuitive profiling, with auto-push/pop. + * + * @param frame ID of frame. + * @return {@link AutoCloseable} implementation for use + * in try-with-resources. + */ default ProfileFrame profile(String frame) { push(frame); return new ProfileFrame(() -> pop(frame)); } - default void reset() { - // todo: impl - } + /** + * Clear the profiler data. + */ + void reset(); } diff --git a/common/src/main/java/com/dfsek/terra/profiler/ProfilerImpl.java b/common/src/main/java/com/dfsek/terra/profiler/ProfilerImpl.java index 0ffd824e1..f91deecd1 100644 --- a/common/src/main/java/com/dfsek/terra/profiler/ProfilerImpl.java +++ b/common/src/main/java/com/dfsek/terra/profiler/ProfilerImpl.java @@ -83,4 +83,9 @@ public class ProfilerImpl implements Profiler { })); return map; } + + @Override + public void reset() { + accessibleThreadMaps.forEach(Map::clear); + } } 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 878890bff..65858b8ad 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 @@ -68,10 +68,4 @@ public class FloraRegistry extends OpenRegistry { private BlockData data(String s) { return main.getWorldHandle().createBlockData(s); } - - - @Override - public Flora get(String identifier) { - return super.get(identifier); - } } 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 32b2c1421..f92635ef3 100644 --- a/common/src/main/java/com/dfsek/terra/world/TerraWorld.java +++ b/common/src/main/java/com/dfsek/terra/world/TerraWorld.java @@ -25,7 +25,7 @@ public class TerraWorld { public TerraWorld(World w, ConfigPack c, TerraPlugin main) { - if(!isTerraWorld(w)) throw new IllegalArgumentException("World " + w + " is not a Terra World!"); + if(!w.isTerraWorld()) throw new IllegalArgumentException("World " + w + " is not a Terra World!"); this.world = w; config = c.toWorldConfig(this); this.provider = config.getProvider(); @@ -34,17 +34,11 @@ public class TerraWorld { safe = true; } - 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; diff --git a/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator3D.java b/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator3D.java index 4e4c17e81..678d3b2a6 100644 --- a/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator3D.java +++ b/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator3D.java @@ -50,7 +50,6 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator { private final Carver carver; - public DefaultChunkGenerator3D(ConfigPack c, TerraPlugin main) { this.configPack = c; this.main = main; @@ -104,9 +103,10 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator { @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(ProfileFrame ignore = main.getProfiler().profile("chunk_base_3d")) { + TerraWorld tw = main.getWorld(world); + BiomeProvider grid = tw.getBiomeProvider(); + if(!tw.isSafe()) return chunk; int xOrig = (chunkX << 4); int zOrig = (chunkZ << 4); @@ -120,7 +120,7 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator { int cx = xOrig + x; int cz = zOrig + z; - TerraBiome b = grid.getBiome(xOrig + x, zOrig + z); + TerraBiome b = grid.getBiome(cx, cz); BiomeTemplate c = ((UserDefinedBiome) b).getConfig(); int sea = c.getSeaLevel(); @@ -227,17 +227,20 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator { return false; } + @SuppressWarnings({"try"}) 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(int z = 0; z < 4; z++) { - int cx = xOrig + (x << 2); - int cz = zOrig + (z << 2); - TerraBiome b = grid.getBiome(cx, cz); + try(ProfileFrame ignore = main.getProfiler().profile("biomes")) { + int xOrig = (chunkX << 4); + int zOrig = (chunkZ << 4); + BiomeProvider grid = main.getWorld(world).getBiomeProvider(); + for(int x = 0; x < 4; x++) { + 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(cx, cz, b.getVanillaBiomes().get(b.getGenerator(world).getBiomeNoise(), cx, 0, cz)); + biome.setBiome(cx, cz, b.getVanillaBiomes().get(b.getGenerator(world).getBiomeNoise(), cx, 0, cz)); + } } } } 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 64d4577b1..e9965d49b 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 @@ -25,7 +25,7 @@ public class SamplerCache { 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()); + return world.getWorld().getTerraGenerator().createSampler(cx, cz, world.getBiomeProvider(), world.getWorld(), world.getConfig().getTemplate().getElevationBlend()); } }); } 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 b3ad924cd..99c97f411 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 @@ -33,7 +33,7 @@ public class FloraPopulator implements TerraBlockPopulator { public void populate(@NotNull World world, @NotNull Chunk chunk) { TerraWorld tw = main.getWorld(world); try(ProfileFrame ignore = main.getProfiler().profile("flora")) { - if(tw.getConfig().getTemplate().disableCarvers()) return; + if(tw.getConfig().getTemplate().disableFlora()) return; if(!tw.isSafe()) return; BiomeProvider provider = tw.getBiomeProvider(); 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 2e9c042c9..3d5c0966a 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 @@ -28,7 +28,7 @@ public class OrePopulator implements TerraBlockPopulator { public void populate(@NotNull World world, @NotNull Chunk chunk) { TerraWorld tw = main.getWorld(world); try(ProfileFrame ignore = main.getProfiler().profile("ore")) { - if(tw.getConfig().getTemplate().disableCarvers()) return; + if(tw.getConfig().getTemplate().disableOres()) return; if(!tw.isSafe()) return; for(int cx = -1; cx <= 1; cx++) { 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 4566d22ca..30346917c 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 @@ -32,7 +32,7 @@ public class StructurePopulator implements TerraBlockPopulator, Chunkified { public void populate(@NotNull World world, @NotNull Chunk chunk) { TerraWorld tw = main.getWorld(world); try(ProfileFrame ignore = main.getProfiler().profile("structure")) { - if(tw.getConfig().getTemplate().disableCarvers()) return; + if(tw.getConfig().getTemplate().disableStructures()) return; int cx = (chunk.getX() << 4); int cz = (chunk.getZ() << 4); 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 9cb63c96e..5dd58fb92 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 @@ -33,7 +33,7 @@ public class TreePopulator implements TerraBlockPopulator { public void populate(@NotNull World world, @NotNull Chunk chunk) { TerraWorld tw = main.getWorld(world); try(ProfileFrame ignore = main.getProfiler().profile("tree")) { - if(tw.getConfig().getTemplate().disableCarvers()) return; + if(tw.getConfig().getTemplate().disableTrees()) return; if(!tw.isSafe()) return; BiomeProvider provider = tw.getBiomeProvider(); diff --git a/common/src/test/java/biome/DistributionTest.java b/common/src/test/java/biome/DistributionTest.java new file mode 100644 index 000000000..e69de29bb diff --git a/common/src/test/java/biome/ImageTest.java b/common/src/test/java/biome/ImageTest.java new file mode 100644 index 000000000..e69de29bb diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 000000000..94dc0b5ce --- /dev/null +++ b/gradle.properties @@ -0,0 +1,10 @@ +# Magic options for more perf +org.gradle.jvmargs=-Xmx2048M -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC +org.gradle.vfs.watch=true +kapt.use.worker.api=true +kapt.include.compile.classpath=false +org.gradle.parallel=true +org.gradle.caching=true +org.gradle.warning.mode=all +#org.gradle.logging.level=info +#org.gradle.configureondemand=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aec6aa17c..a29c5e5c5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists 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 6e8f30a0e..1a4d3cce6 100644 --- a/platforms/bukkit/build.gradle.kts +++ b/platforms/bukkit/build.gradle.kts @@ -70,8 +70,8 @@ fun installServer(dir: String) { // Cloning test setup. gitClone("https://github.com/PolyhedralDev/WorldGenTestServer") // Copying plugins - Files.move(Paths.get("WorldGenTestServer/plugins"), - Paths.get("$testDir/$dir/plugins"), + Files.move(file("WorldGenTestServer/plugins").toPath(), + file("$testDir/$dir/plugins").toPath(), StandardCopyOption.REPLACE_EXISTING) // Copying config val serverText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/server.properties").readText() 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 d4cc682fb..acc83d986 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 @@ -34,6 +34,7 @@ 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.bukkit.world.BukkitWorld; import com.dfsek.terra.commands.CommandUtil; import com.dfsek.terra.config.GenericLoaders; import com.dfsek.terra.config.PluginConfig; @@ -264,14 +265,15 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin { return checkedRegistry; } - public TerraWorld getWorld(World w) { - if(!TerraWorld.isTerraWorld(w)) + public TerraWorld getWorld(World world) { + BukkitWorld w = (BukkitWorld) world; + if(!w.isTerraWorld()) 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, ((TerraChunkGenerator) w.getGenerator().getHandle()).getConfigPack(), this); } - return worldMap.computeIfAbsent(w, world -> new TerraWorld(w, worlds.get(w.getName()), this)); + return worldMap.computeIfAbsent(w, w2 -> new TerraWorld(w, worlds.get(w.getName()), this)); } @Override 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 cae7325db..67b7148e6 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 @@ -52,7 +52,7 @@ public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements Gener } public static synchronized void fixChunk(Chunk c) { - if(!TerraWorld.isTerraWorld(c.getWorld())) throw new IllegalArgumentException(); + if(!c.getWorld().isTerraWorld()) throw new IllegalArgumentException(); popMap.get(c.getWorld()).checkNeighbors(c.getX(), c.getZ(), c.getWorld()); } 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 9e2a65407..5ea6f4bd5 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 @@ -44,7 +44,7 @@ public class CommonListener implements Listener { public void onSaplingGrow(StructureGrowEvent e) { if(e.isCancelled()) return; World bukkit = BukkitAdapter.adapt(e.getWorld()); - if(!TerraWorld.isTerraWorld(bukkit)) return; + if(!bukkit.isTerraWorld()) return; TerraWorld tw = main.getWorld(bukkit); WorldConfig c = tw.getConfig(); if(c.getTemplate().isDisableSaplings()) return; 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 aebdd017d..f2013e7a6 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 @@ -18,7 +18,7 @@ public class PaperListener implements Listener { @EventHandler public void onStructureLocate(StructureLocateEvent e) { - if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getWorld()))) return; + if(!BukkitAdapter.adapt(e.getWorld()).isTerraWorld()) return; e.setResult(null); // Assume no result. String name = "minecraft:" + e.getType().getName(); main.getDebugLogger().info("Overriding structure location 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 0260bf215..bbe0a1947 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 @@ -34,7 +34,7 @@ public class SpigotListener implements Listener { Entity entity = e.getEntity(); if(e.getEntityType().equals(EntityType.ENDER_SIGNAL)) { main.getDebugLogger().info("Detected Ender Signal..."); - if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return; + if(!BukkitAdapter.adapt(e.getEntity().getWorld()).isTerraWorld()) return; TerraWorld tw = main.getWorld(BukkitAdapter.adapt(e.getEntity().getWorld())); EnderSignal signal = (EnderSignal) entity; TerraStructure config = tw.getConfig().getRegistry(TerraStructure.class).get(tw.getConfig().getTemplate().getLocatable().get("STRONGHOLD")); @@ -53,7 +53,7 @@ public class SpigotListener implements Listener { @EventHandler public void onCartographerChange(VillagerAcquireTradeEvent e) { - if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return; + if(!BukkitAdapter.adapt(e.getEntity().getWorld()).isTerraWorld()) return; if(!(e.getEntity() instanceof Villager)) return; if(((Villager) e.getEntity()).getProfession().equals(Villager.Profession.CARTOGRAPHER)) { main.logger().severe("Prevented server crash by stopping Cartographer villager from spawning."); @@ -65,7 +65,7 @@ public class SpigotListener implements Listener { @EventHandler public void onCartographerLevel(VillagerCareerChangeEvent e) { - if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return; + if(!BukkitAdapter.adapt(e.getEntity().getWorld()).isTerraWorld()) return; if(e.getProfession().equals(Villager.Profession.CARTOGRAPHER)) { 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"); diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/ChunkCoordinate.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/ChunkCoordinate.java index 6e2c87e00..a68e575fa 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/ChunkCoordinate.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/ChunkCoordinate.java @@ -2,6 +2,7 @@ package com.dfsek.terra.bukkit.population; import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.bukkit.world.BukkitWorld; import java.io.Serializable; import java.util.UUID; @@ -21,7 +22,7 @@ public class ChunkCoordinate implements Serializable { public ChunkCoordinate(Chunk c) { this.x = c.getX(); this.z = c.getZ(); - this.worldID = c.getWorld().getUID(); + this.worldID = ((BukkitWorld) c.getWorld()).getUID(); } public UUID getWorldID() { diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/Gaea.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/Gaea.java deleted file mode 100644 index 0b38547d6..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/Gaea.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.bukkit.population; - - -import com.dfsek.terra.api.platform.world.World; - -import java.io.File; - -public class Gaea { - private static boolean debug; - - public static File getGaeaFolder(World w) { - File f = new File(w.getWorldFolder(), "gaea"); - f.mkdirs(); - return f; - } - - public static boolean isDebug() { - return debug; - } -} 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 583aa0fb9..ca3f3e8aa 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 @@ -9,6 +9,7 @@ import com.dfsek.terra.api.world.generation.TerraChunkGenerator; import com.dfsek.terra.bukkit.TerraBukkitPlugin; import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.profiler.ProfileFrame; +import com.dfsek.terra.bukkit.world.BukkitWorld; import org.bukkit.generator.BlockPopulator; import org.jetbrains.annotations.NotNull; @@ -32,21 +33,28 @@ public class PopulationManager extends BlockPopulator { @SuppressWarnings("unchecked") public synchronized void saveBlocks(World w) throws IOException { - File f = new File(Gaea.getGaeaFolder(w), "chunks.bin"); + File f = new File(getDataFolder(w), "chunks.bin"); f.createNewFile(); SerializationUtil.toFile((HashSet) needsPop.clone(), f); } @SuppressWarnings("unchecked") public synchronized void loadBlocks(World w) throws IOException, ClassNotFoundException { - File f = new File(Gaea.getGaeaFolder(w), "chunks.bin"); + File f = new File(getDataFolder(w), "chunks.bin"); needsPop.addAll((HashSet) SerializationUtil.fromFile(f)); } + public static File getDataFolder(World w) { + File f = new File(((BukkitWorld) w).getWorldFolder(), "gaea"); + f.mkdirs(); + return f; + } + // Synchronize to prevent chunks from being queued for population multiple times. - public synchronized void checkNeighbors(int x, int z, World w) { - ChunkCoordinate c = new ChunkCoordinate(x, z, w.getUID()); + public synchronized void checkNeighbors(int x, int z, World world) { + BukkitWorld w = (BukkitWorld) world; + ChunkCoordinate c = new ChunkCoordinate(x, z, (w).getUID()); if(w.isChunkGenerated(x + 1, z) && w.isChunkGenerated(x - 1, z) && w.isChunkGenerated(x, z + 1) 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 294314cbf..48f3b7863 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 @@ -37,17 +37,14 @@ public class BukkitWorld implements World { return new BukkitChunkGenerator(delegate.getGenerator()); } - @Override public String getName() { return delegate.getName(); } - @Override public UUID getUID() { return delegate.getUID(); } - @Override public boolean isChunkGenerated(int x, int z) { return delegate.isChunkGenerated(x, z); } @@ -57,7 +54,6 @@ public class BukkitWorld implements World { return BukkitAdapter.adapt(delegate.getChunkAt(x, z)); } - @Override public File getWorldFolder() { return delegate.getWorldFolder(); } diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index cece1888a..38aafb791 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -33,6 +33,7 @@ dependencies { configure { accessWidener("src/main/resources/terra.accesswidener") + refmapName = "terra-refmap.json" } val remapped = tasks.register("remapShadedJar") { @@ -46,12 +47,12 @@ val remapped = tasks.register("remapShadedJar") { } -tasks.register("publishModrinth") { +tasks.register("publishModrinthFabric") { dependsOn("remapShadedJar") group = "fabric" token = System.getenv("MODRINTH_SECRET") projectId = "FIlZB9L0" - versionNumber = project.version.toString() + versionNumber = "${project.version}-fabric" uploadFile = remapped.get().archiveFile.get().asFile releaseType = "beta" addGameVersion("1.16.4") diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAdapter.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAdapter.java new file mode 100644 index 000000000..62037173c --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAdapter.java @@ -0,0 +1,224 @@ +package com.dfsek.terra.fabric; + +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.block.Axis; +import com.dfsek.terra.api.platform.block.BlockFace; +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.state.Container; +import com.dfsek.terra.api.platform.block.state.MobSpawner; +import com.dfsek.terra.api.platform.block.state.Sign; +import com.dfsek.terra.fabric.block.FabricBlockData; +import com.dfsek.terra.fabric.block.data.FabricDirectional; +import com.dfsek.terra.fabric.block.data.FabricMultipleFacing; +import com.dfsek.terra.fabric.block.data.FabricOrientable; +import com.dfsek.terra.fabric.block.data.FabricRotatable; +import com.dfsek.terra.fabric.block.data.FabricSlab; +import com.dfsek.terra.fabric.block.data.FabricStairs; +import com.dfsek.terra.fabric.block.data.FabricWaterlogged; +import net.minecraft.block.BlockState; +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.block.enums.BlockHalf; +import net.minecraft.block.enums.SlabType; +import net.minecraft.block.enums.StairShape; +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 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 com.dfsek.terra.api.platform.block.state.BlockState adapt(com.dfsek.terra.api.platform.block.Block block) { + WorldAccess worldAccess = (WorldAccess) block.getLocation().getWorld(); + + BlockEntity entity = worldAccess.getBlockEntity(adapt(block.getLocation().toVector())); + if(entity instanceof SignBlockEntity) { + return (Sign) entity; + } else if(entity instanceof MobSpawnerBlockEntity) { + return (MobSpawner) entity; + } else if(entity instanceof LootableContainerBlockEntity) { + return (Container) entity; + } + return null; + } + + public static Stairs.Shape adapt(StairShape shape) { + switch(shape) { + case OUTER_RIGHT: + return Stairs.Shape.OUTER_RIGHT; + case INNER_RIGHT: + return Stairs.Shape.INNER_RIGHT; + case OUTER_LEFT: + return Stairs.Shape.OUTER_LEFT; + case INNER_LEFT: + return Stairs.Shape.INNER_LEFT; + case STRAIGHT: + return Stairs.Shape.STRAIGHT; + default: + throw new IllegalStateException(); + } + } + + public static Bisected.Half adapt(BlockHalf half) { + switch(half) { + case BOTTOM: + return Bisected.Half.BOTTOM; + case TOP: + return Bisected.Half.TOP; + default: + throw new IllegalStateException(); + } + } + + public static BlockFace adapt(Direction direction) { + switch(direction) { + case DOWN: + return BlockFace.DOWN; + case UP: + return BlockFace.UP; + case WEST: + return BlockFace.WEST; + case EAST: + return BlockFace.EAST; + case NORTH: + return BlockFace.NORTH; + case SOUTH: + return BlockFace.SOUTH; + default: + throw new IllegalStateException(); + } + } + + public static Slab.Type adapt(SlabType type) { + switch(type) { + case BOTTOM: + return Slab.Type.BOTTOM; + case TOP: + return Slab.Type.TOP; + case DOUBLE: + return Slab.Type.DOUBLE; + default: + throw new IllegalStateException(); + } + } + + public static StairShape adapt(Stairs.Shape shape) { + switch(shape) { + case STRAIGHT: + return StairShape.STRAIGHT; + case INNER_LEFT: + return StairShape.INNER_LEFT; + case OUTER_LEFT: + return StairShape.OUTER_LEFT; + case INNER_RIGHT: + return StairShape.INNER_RIGHT; + case OUTER_RIGHT: + return StairShape.OUTER_RIGHT; + default: + throw new IllegalStateException(); + } + } + + public static BlockHalf adapt(Bisected.Half half) { + switch(half) { + case TOP: + return BlockHalf.TOP; + case BOTTOM: + return BlockHalf.BOTTOM; + default: + throw new IllegalStateException(); + } + } + + public static SlabType adapt(Slab.Type type) { + switch(type) { + case DOUBLE: + return SlabType.DOUBLE; + case TOP: + return SlabType.TOP; + case BOTTOM: + return SlabType.BOTTOM; + default: + throw new IllegalStateException(); + } + } + + public static Axis adapt(Direction.Axis axis) { + switch(axis) { + case X: + return Axis.X; + case Y: + return Axis.Y; + case Z: + return Axis.Z; + default: + throw new IllegalStateException(); + } + } + + public static Direction.Axis adapt(Axis axis) { + switch(axis) { + case Z: + return Direction.Axis.Z; + case Y: + return Direction.Axis.Y; + case X: + return Direction.Axis.X; + default: + throw new IllegalStateException(); + } + } +} 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 06d24752b..78b6c123d 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 @@ -18,6 +18,7 @@ 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.entity.Entity; import com.dfsek.terra.api.platform.handle.ItemHandle; import com.dfsek.terra.api.platform.handle.WorldHandle; import com.dfsek.terra.api.platform.world.Tree; @@ -36,16 +37,13 @@ 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.config.templates.BiomeTemplate; -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.fabric.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.fabric.generation.PopulatorFeature; +import com.dfsek.terra.fabric.generation.TerraBiomeSource; +import com.dfsek.terra.fabric.handle.FabricItemHandle; +import com.dfsek.terra.fabric.handle.FabricWorldHandle; +import com.dfsek.terra.fabric.mixin.access.BiomeEffectsAccessor; +import com.dfsek.terra.fabric.mixin.access.GeneratorTypeAccessor; import com.dfsek.terra.profiler.Profiler; import com.dfsek.terra.profiler.ProfilerImpl; import com.dfsek.terra.registry.exception.DuplicateEntryException; @@ -54,6 +52,7 @@ 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 com.mojang.brigadier.exceptions.CommandSyntaxException; import net.fabricmc.api.EnvType; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; @@ -69,7 +68,6 @@ import net.minecraft.util.registry.RegistryKey; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.BiomeEffects; import net.minecraft.world.biome.GenerationSettings; -import net.minecraft.world.biome.SpawnSettings; import net.minecraft.world.gen.GenerationStep; import net.minecraft.world.gen.chunk.ChunkGenerator; import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; @@ -77,7 +75,6 @@ import net.minecraft.world.gen.decorator.Decorator; import net.minecraft.world.gen.decorator.NopeDecoratorConfig; import net.minecraft.world.gen.feature.ConfiguredFeature; import net.minecraft.world.gen.feature.ConfiguredFeatures; -import net.minecraft.world.gen.feature.DefaultBiomeFeatures; import net.minecraft.world.gen.feature.DefaultFeatureConfig; import net.minecraft.world.gen.feature.FeatureConfig; import net.minecraft.world.gen.surfacebuilder.SurfaceBuilder; @@ -158,10 +155,16 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { public TerraWorld getWorld(World world) { return worldMap.computeIfAbsent(world.getSeed(), w -> { logger.info("Loading world " + w); - return new TerraWorld(world, ((FabricChunkGeneratorWrapper) ((FabricChunkGenerator) world.getGenerator()).getHandle()).getPack(), this); + return new TerraWorld(world, ((FabricChunkGeneratorWrapper) world.getGenerator()).getPack(), this); }); } + public TerraWorld getWorld(long seed) { + TerraWorld world = worldMap.get(seed); + if(world == null) throw new IllegalArgumentException("No world exists with seed " + seed); + return world; + } + @Override public Logger logger() { return logger; @@ -238,41 +241,37 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { genericLoaders.register(registry); registry .registerLoader(BlockData.class, (t, o, l) -> worldHandle.createBlockData((String) o)) - .registerLoader(com.dfsek.terra.api.platform.world.Biome.class, (t, o, l) -> new FabricBiome(biomeFixer.translate((String) o))); + .registerLoader(com.dfsek.terra.api.platform.world.Biome.class, (t, o, l) -> biomeFixer.translate((String) o)); } private Biome createBiome(BiomeBuilder biome) { - SpawnSettings.Builder spawnSettings = new SpawnSettings.Builder(); - DefaultBiomeFeatures.addFarmAnimals(spawnSettings); - DefaultBiomeFeatures.addMonsters(spawnSettings, 95, 5, 100); - BiomeTemplate template = biome.getTemplate(); Map colors = template.getColors(); - Biome vanilla = ((FabricBiome) new ArrayList<>(biome.getVanillaBiomes().getContents()).get(0)).getHandle(); + Biome vanilla = (Biome) (new ArrayList<>(biome.getVanillaBiomes().getContents()).get(0)).getHandle(); GenerationSettings.Builder generationSettings = new GenerationSettings.Builder(); 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); + BiomeEffectsAccessor accessor = (BiomeEffectsAccessor) vanilla.getEffects(); BiomeEffects.Builder effects = new BiomeEffects.Builder() - .waterColor(colors.getOrDefault("water", vanilla.getEffects().waterColor)) - .waterFogColor(colors.getOrDefault("water-fog", vanilla.getEffects().waterFogColor)) - .fogColor(colors.getOrDefault("fog", vanilla.getEffects().fogColor)) - .skyColor(colors.getOrDefault("sky", vanilla.getEffects().skyColor)) - .grassColorModifier(vanilla.getEffects().grassColorModifier); + .waterColor(colors.getOrDefault("water", accessor.getWaterColor())) + .waterFogColor(colors.getOrDefault("water-fog", accessor.getWaterFogColor())) + .fogColor(colors.getOrDefault("fog", accessor.getFogColor())) + .skyColor(colors.getOrDefault("sky", accessor.getSkyColor())) + .grassColorModifier(accessor.getGrassColorModifier()); if(colors.containsKey("grass")) { effects.grassColor(colors.get("grass")); } else { - vanilla.getEffects().grassColor.ifPresent(effects::grassColor); + accessor.getGrassColor().ifPresent(effects::grassColor); } - vanilla.getEffects().foliageColor.ifPresent(effects::foliageColor); if(colors.containsKey("foliage")) { effects.foliageColor(colors.get("foliage")); } else { - vanilla.getEffects().foliageColor.ifPresent(effects::foliageColor); + accessor.getFoliageColor().ifPresent(effects::foliageColor); } return new Biome.Builder() @@ -283,7 +282,7 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { .temperature(vanilla.getTemperature()) .downfall(vanilla.getDownfall()) .effects(effects.build()) - .spawnSettings(spawnSettings.build()) + .spawnSettings(vanilla.getSpawnSettings()) .generationSettings(generationSettings.build()) .build(); } @@ -328,7 +327,7 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { }; //noinspection ConstantConditions ((GeneratorTypeAccessor) generatorType).setTranslationKey(new LiteralText("Terra:" + pack.getTemplate().getID())); - GeneratorTypeAccessor.getVALUES().add(generatorType); + GeneratorTypeAccessor.getValues().add(generatorType); }); } @@ -360,7 +359,11 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { private RequiredArgumentBuilder assemble(RequiredArgumentBuilder in, CommandManager manager) { return in.suggests((context, builder) -> { List args = parseCommand(context.getInput()); - CommandSender sender = FabricAdapter.adapt(context.getSource()); + CommandSender sender = (CommandSender) context.getSource(); + try { + sender = (Entity) context.getSource().getEntityOrThrow(); + } catch(CommandSyntaxException ignore) { + } try { manager.tabComplete(args.remove(0), sender, args).forEach(builder::suggest); } catch(CommandException e) { @@ -369,8 +372,13 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { return builder.buildFuture(); }).executes(context -> { List args = parseCommand(context.getInput()); + CommandSender sender = (CommandSender) context.getSource(); try { - manager.execute(args.remove(0), FabricAdapter.adapt(context.getSource()), args); + sender = (Entity) context.getSource().getEntityOrThrow(); + } catch(CommandSyntaxException ignore) { + } + try { + manager.execute(args.remove(0), sender, args); } catch(CommandException e) { context.getSource().sendError(new LiteralText(e.getMessage())); } @@ -441,7 +449,7 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { private void injectTree(CheckedRegistry registry, String id, ConfiguredFeature tree) { try { - registry.add(id, new FabricTree(tree)); + registry.add(id, (Tree) tree); } catch(DuplicateEntryException ignore) { } } 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/block/FabricBlock.java similarity index 89% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlock.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/FabricBlock.java index 9e0b440ac..b53bff68f 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/block/FabricBlock.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.fabric.world.block; +package com.dfsek.terra.fabric.block; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.Block; @@ -6,9 +6,8 @@ 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.state.BlockState; -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 com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.fabric.FabricAdapter; import net.minecraft.block.FluidBlock; import net.minecraft.util.math.BlockPos; import net.minecraft.world.WorldAccess; @@ -35,7 +34,7 @@ public class FabricBlock implements Block { @Override public BlockState getState() { - return FabricBlockState.newInstance(this); + return FabricAdapter.adapt(this); } @Override @@ -51,7 +50,7 @@ public class FabricBlock implements Block { @Override public Location getLocation() { - return FabricAdapter.adapt(delegate.position).toLocation(new FabricWorldAccess(delegate.worldAccess)); + return FabricAdapter.adapt(delegate.position).toLocation((World) delegate.worldAccess); } @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/block/FabricBlockData.java similarity index 85% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlockData.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/FabricBlockData.java index 2467e992a..6fd723bfb 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/block/FabricBlockData.java @@ -1,11 +1,10 @@ -package com.dfsek.terra.fabric.world.block; +package com.dfsek.terra.fabric.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 com.dfsek.terra.fabric.mixin.access.StateAccessor; 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; @@ -19,7 +18,7 @@ public class FabricBlockData implements BlockData { @Override public BlockType getBlockType() { - return FabricAdapter.adapt(delegate.getBlock()); + return (BlockType) delegate.getBlock(); } @Override @@ -41,7 +40,7 @@ public class FabricBlockData implements BlockData { 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(delegate.getEntries().entrySet().stream().map(StateAccessor.getPropertyMapPrinter()).collect(Collectors.joining(","))); data.append(']'); } return data.toString(); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricAnaloguePowerable.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricAnaloguePowerable.java similarity index 84% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricAnaloguePowerable.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricAnaloguePowerable.java index 2e7a55347..b2fab164e 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricAnaloguePowerable.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricAnaloguePowerable.java @@ -1,7 +1,7 @@ -package com.dfsek.terra.fabric.world.block.data; +package com.dfsek.terra.fabric.block.data; import com.dfsek.terra.api.platform.block.data.AnaloguePowerable; -import com.dfsek.terra.fabric.world.block.FabricBlockData; +import com.dfsek.terra.fabric.block.FabricBlockData; import net.minecraft.block.BlockState; /** 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/block/data/FabricDirectional.java similarity index 88% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricDirectional.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricDirectional.java index 21584a8e8..4d15d1c16 100644 --- 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/block/data/FabricDirectional.java @@ -1,9 +1,9 @@ -package com.dfsek.terra.fabric.world.block.data; +package com.dfsek.terra.fabric.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 com.dfsek.terra.fabric.FabricAdapter; +import com.dfsek.terra.fabric.block.FabricBlockData; import net.minecraft.block.BlockState; import net.minecraft.state.property.DirectionProperty; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricMultipleFacing.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricMultipleFacing.java similarity index 95% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricMultipleFacing.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricMultipleFacing.java index c4c1bf40f..d1caae8e1 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricMultipleFacing.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricMultipleFacing.java @@ -1,8 +1,8 @@ -package com.dfsek.terra.fabric.world.block.data; +package com.dfsek.terra.fabric.block.data; import com.dfsek.terra.api.platform.block.BlockFace; import com.dfsek.terra.api.platform.block.data.MultipleFacing; -import com.dfsek.terra.fabric.world.block.FabricBlockData; +import com.dfsek.terra.fabric.block.FabricBlockData; import net.minecraft.block.BlockState; import net.minecraft.state.property.Properties; 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/block/data/FabricOrientable.java similarity index 75% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricOrientable.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricOrientable.java index 5c9e179d0..1633df9ab 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/block/data/FabricOrientable.java @@ -1,8 +1,9 @@ -package com.dfsek.terra.fabric.world.block.data; +package com.dfsek.terra.fabric.block.data; 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 com.dfsek.terra.fabric.FabricAdapter; +import com.dfsek.terra.fabric.block.FabricBlockData; import net.minecraft.block.BlockState; import net.minecraft.state.property.EnumProperty; import net.minecraft.util.math.Direction; @@ -26,11 +27,11 @@ public class FabricOrientable extends FabricBlockData implements Orientable { @Override public Axis getAxis() { - return FabricEnumAdapter.adapt(getHandle().get(property)); + return FabricAdapter.adapt(getHandle().get(property)); } @Override public void setAxis(Axis axis) { - delegate = delegate.with(property, FabricEnumAdapter.adapt(axis)); + delegate = delegate.with(property, FabricAdapter.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/block/data/FabricRotatable.java similarity index 97% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricRotatable.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricRotatable.java index a238f21e1..4b7a971ea 100644 --- 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/block/data/FabricRotatable.java @@ -1,8 +1,8 @@ -package com.dfsek.terra.fabric.world.block.data; +package com.dfsek.terra.fabric.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 com.dfsek.terra.fabric.block.FabricBlockData; import net.minecraft.block.BlockState; import net.minecraft.state.property.Properties; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricSlab.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricSlab.java similarity index 61% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricSlab.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricSlab.java index a6ca5f5de..390702582 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricSlab.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricSlab.java @@ -1,6 +1,7 @@ -package com.dfsek.terra.fabric.world.block.data; +package com.dfsek.terra.fabric.block.data; import com.dfsek.terra.api.platform.block.data.Slab; +import com.dfsek.terra.fabric.FabricAdapter; import net.minecraft.block.BlockState; import net.minecraft.state.property.Properties; @@ -11,11 +12,11 @@ public class FabricSlab extends FabricWaterlogged implements Slab { @Override public Type getType() { - return FabricEnumAdapter.adapt(delegate.get(Properties.SLAB_TYPE)); + return FabricAdapter.adapt(delegate.get(Properties.SLAB_TYPE)); } @Override public void setType(Type type) { - delegate = delegate.with(Properties.SLAB_TYPE, FabricEnumAdapter.adapt(type)); + delegate = delegate.with(Properties.SLAB_TYPE, FabricAdapter.adapt(type)); } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricStairs.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricStairs.java similarity index 67% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricStairs.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricStairs.java index ec268f784..098cd75d6 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricStairs.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricStairs.java @@ -1,7 +1,8 @@ -package com.dfsek.terra.fabric.world.block.data; +package com.dfsek.terra.fabric.block.data; import com.dfsek.terra.api.platform.block.BlockFace; import com.dfsek.terra.api.platform.block.data.Stairs; +import com.dfsek.terra.fabric.FabricAdapter; import net.minecraft.block.BlockState; import net.minecraft.state.property.Properties; @@ -12,31 +13,31 @@ public class FabricStairs extends FabricWaterlogged implements Stairs { @Override public Shape getShape() { - return FabricEnumAdapter.adapt(getHandle().get(Properties.STAIR_SHAPE)); + return FabricAdapter.adapt(getHandle().get(Properties.STAIR_SHAPE)); } @Override public void setShape(Shape shape) { - super.delegate = getHandle().with(Properties.STAIR_SHAPE, FabricEnumAdapter.adapt(shape)); + super.delegate = getHandle().with(Properties.STAIR_SHAPE, FabricAdapter.adapt(shape)); } @Override public Half getHalf() { - return FabricEnumAdapter.adapt(getHandle().get(Properties.BLOCK_HALF)); + return FabricAdapter.adapt(getHandle().get(Properties.BLOCK_HALF)); } @Override public void setHalf(Half half) { - super.delegate = getHandle().with(Properties.BLOCK_HALF, FabricEnumAdapter.adapt(half)); + super.delegate = getHandle().with(Properties.BLOCK_HALF, FabricAdapter.adapt(half)); } @Override public BlockFace getFacing() { - return FabricEnumAdapter.adapt(getHandle().get(Properties.HORIZONTAL_FACING)); + return FabricAdapter.adapt(getHandle().get(Properties.HORIZONTAL_FACING)); } @Override public void setFacing(BlockFace facing) { - super.delegate = getHandle().with(Properties.HORIZONTAL_FACING, FabricEnumAdapter.adapt(facing)); + super.delegate = getHandle().with(Properties.HORIZONTAL_FACING, FabricAdapter.adapt(facing)); } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricWaterlogged.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricWaterlogged.java similarity index 84% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricWaterlogged.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricWaterlogged.java index 95960e295..7e3636bde 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricWaterlogged.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricWaterlogged.java @@ -1,7 +1,7 @@ -package com.dfsek.terra.fabric.world.block.data; +package com.dfsek.terra.fabric.block.data; import com.dfsek.terra.api.platform.block.data.Waterlogged; -import com.dfsek.terra.fabric.world.block.FabricBlockData; +import com.dfsek.terra.fabric.block.FabricBlockData; import net.minecraft.block.BlockState; import net.minecraft.state.property.Properties; 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 deleted file mode 100644 index a8db1bb54..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/command/FabricCommandAdapter.java +++ /dev/null @@ -1,7 +0,0 @@ -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 deleted file mode 100644 index 392aaf1af..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/command/StringListArgumentType.java +++ /dev/null @@ -1,17 +0,0 @@ -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/world/generator/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java similarity index 63% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGeneratorWrapper.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index a15267e2d..39a4f9fd5 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/generation/FabricChunkGeneratorWrapper.java @@ -1,25 +1,29 @@ -package com.dfsek.terra.fabric.world.generator; +package com.dfsek.terra.fabric.generation; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.platform.world.generator.ChunkData; 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.api.world.locate.AsyncStructureFinder; import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.fabric.FabricAdapter; 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.TerraWorld; 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; -import com.dfsek.terra.world.population.TreePopulator; +import com.dfsek.terra.world.generation.math.samplers.Sampler; +import com.dfsek.terra.world.population.items.TerraStructure; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.jafama.FastMath; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; +import net.minecraft.server.world.ServerWorld; import net.minecraft.structure.StructureManager; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.util.registry.DynamicRegistryManager; +import net.minecraft.util.registry.Registry; import net.minecraft.world.BlockView; import net.minecraft.world.ChunkRegion; import net.minecraft.world.Heightmap; @@ -31,6 +35,12 @@ import net.minecraft.world.gen.StructureAccessor; import net.minecraft.world.gen.chunk.ChunkGenerator; import net.minecraft.world.gen.chunk.StructuresConfig; import net.minecraft.world.gen.chunk.VerticalBlockSample; +import net.minecraft.world.gen.feature.StructureFeature; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; public class FabricChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper { private final long seed; @@ -77,6 +87,28 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener } + @Nullable + @Override + public BlockPos locateStructure(ServerWorld world, StructureFeature feature, BlockPos center, int radius, boolean skipExistingChunks) { + String name = Objects.requireNonNull(Registry.STRUCTURE_FEATURE.getId(feature)).toString(); + TerraWorld terraWorld = TerraFabricPlugin.getInstance().getWorld((World) world); + TerraStructure located = pack.getRegistry(TerraStructure.class).get(pack.getTemplate().getLocatable().get(name)); + if(located != null) { + CompletableFuture result = new CompletableFuture<>(); + AsyncStructureFinder finder = new AsyncStructureFinder(terraWorld.getBiomeProvider(), located, FabricAdapter.adapt(center).toLocation((World) world), 0, 500, location -> { + result.complete(FabricAdapter.adapt(location)); + }, TerraFabricPlugin.getInstance()); + finder.run(); // Do this synchronously. + try { + return result.get(); + } catch(InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + TerraFabricPlugin.getInstance().logger().warning("No overrides are defined for \"" + name + "\""); + return null; + } + @Override public void generateFeatures(ChunkRegion region, StructureAccessor accessor) { super.generateFeatures(region, accessor); @@ -84,8 +116,7 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener @Override public void populateNoise(WorldAccess world, StructureAccessor accessor, Chunk chunk) { - FabricSeededWorldAccess worldAccess = new FabricSeededWorldAccess(world, seed, this); - delegate.generateChunkData(worldAccess, new FastRandom(), chunk.getPos().x, chunk.getPos().z, new FabricChunkData(chunk)); + delegate.generateChunkData((World) world, new FastRandom(), chunk.getPos().x, chunk.getPos().z, (ChunkData) chunk); } @Override @@ -107,7 +138,18 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener @Override public int getHeight(int x, int z, Heightmap.Type heightmapType) { - return 0; + TerraWorld world = TerraFabricPlugin.getInstance().getWorld(seed); + Sampler sampler = world.getConfig().getSamplerCache().getChunk(FastMath.floorDiv(x, 16), FastMath.floorDiv(z, 16)); + int cx = FastMath.floorMod(x, 16); + int cz = FastMath.floorMod(z, 16); + + int height = world.getWorld().getMaxHeight(); + + while (height >= 0 && sampler.sample(cx, height - 1, cz) < 0) { + height--; + } + + return height; } @Override 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/generation/PopulatorFeature.java similarity index 57% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/features/PopulatorFeature.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/PopulatorFeature.java index b284acd43..c58fad225 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/generation/PopulatorFeature.java @@ -1,10 +1,8 @@ -package com.dfsek.terra.fabric.world.features; +package com.dfsek.terra.fabric.generation; -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.FabricWorldAccess; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; import com.mojang.serialization.Codec; import net.minecraft.util.math.BlockPos; import net.minecraft.world.StructureWorldAccess; @@ -25,9 +23,7 @@ public class PopulatorFeature extends Feature { @Override public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) { 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.getHandle().getPopulators().forEach(populator -> populator.populate(world1, chunk)); + gen.getHandle().getPopulators().forEach(populator -> populator.populate((World) world, (Chunk) world)); return true; } } 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/generation/TerraBiomeSource.java similarity index 98% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/TerraBiomeSource.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java index 46b628eac..e2d821192 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/TerraBiomeSource.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.fabric.world; +package com.dfsek.terra.fabric.generation; import com.dfsek.terra.api.world.biome.UserDefinedBiome; import com.dfsek.terra.api.world.biome.provider.BiomeProvider; 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/handle/FabricItemHandle.java similarity index 69% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemHandle.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricItemHandle.java index ef77d9928..4ea99a542 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemHandle.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricItemHandle.java @@ -1,9 +1,8 @@ -package com.dfsek.terra.fabric.inventory; +package com.dfsek.terra.fabric.handle; import com.dfsek.terra.api.platform.handle.ItemHandle; 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; @@ -18,7 +17,7 @@ public class FabricItemHandle implements ItemHandle { @Override public Item createItem(String data) { try { - return FabricAdapter.adapt(new ItemStackArgumentType().parse(new StringReader(data)).getItem()); + return (Item) new ItemStackArgumentType().parse(new StringReader(data)).getItem(); } catch(CommandSyntaxException e) { throw new IllegalArgumentException("Invalid item data \"" + data + "\"", e); } @@ -26,11 +25,11 @@ public class FabricItemHandle implements ItemHandle { @Override public Enchantment getEnchantment(String id) { - return FabricAdapter.adapt(Registry.ENCHANTMENT.get(Identifier.tryParse(id))); + return (Enchantment) (Registry.ENCHANTMENT.get(Identifier.tryParse(id))); } @Override public Set getEnchantments() { - return Registry.ENCHANTMENT.stream().map(FabricAdapter::adapt).collect(Collectors.toSet()); + return Registry.ENCHANTMENT.stream().map(enchantment -> (Enchantment) enchantment).collect(Collectors.toSet()); } } 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/handle/FabricWorldHandle.java similarity index 85% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricWorldHandle.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricWorldHandle.java index 8d6919d56..219968106 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricWorldHandle.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricWorldHandle.java @@ -1,8 +1,9 @@ -package com.dfsek.terra.fabric.world; +package com.dfsek.terra.fabric.handle; 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.FabricAdapter; +import com.dfsek.terra.fabric.block.FabricBlockData; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.block.BlockState; @@ -30,6 +31,6 @@ public class FabricWorldHandle implements WorldHandle { public EntityType getEntity(String id) { Identifier identifier = Identifier.tryParse(id); if(identifier == null) identifier = Identifier.tryParse("minecraft:" + id.toLowerCase(Locale.ROOT)); - return FabricAdapter.adapt(Registry.ENTITY_TYPE.get(identifier)); + return (EntityType) Registry.ENTITY_TYPE.get(identifier); } } 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 deleted file mode 100644 index 8b86f657d..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricInventory.java +++ /dev/null @@ -1,35 +0,0 @@ -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/mixin/MixinGeneratorOptions.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/GeneratorOptionsMixin.java similarity index 83% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/MixinGeneratorOptions.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/GeneratorOptionsMixin.java index aa588249a..3eafe5469 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/MixinGeneratorOptions.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/GeneratorOptionsMixin.java @@ -2,8 +2,8 @@ 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.dfsek.terra.fabric.generation.TerraBiomeSource; +import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; import com.google.common.base.MoreObjects; import net.minecraft.util.registry.DynamicRegistryManager; import net.minecraft.util.registry.Registry; @@ -13,16 +13,17 @@ 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.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; 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) +@Mixin(GeneratorOptions.class) +public abstract class GeneratorOptionsMixin { + @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; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/BiomeEffectsAccessor.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/BiomeEffectsAccessor.java new file mode 100644 index 000000000..2fe2391dc --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/BiomeEffectsAccessor.java @@ -0,0 +1,31 @@ +package com.dfsek.terra.fabric.mixin.access; + +import net.minecraft.world.biome.BiomeEffects; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Optional; + +@Mixin(BiomeEffects.class) +public interface BiomeEffectsAccessor { + @Accessor("fogColor") + int getFogColor(); + + @Accessor("waterColor") + int getWaterColor(); + + @Accessor("waterFogColor") + int getWaterFogColor(); + + @Accessor("skyColor") + int getSkyColor(); + + @Accessor("foliageColor") + Optional getFoliageColor(); + + @Accessor("grassColor") + Optional getGrassColor(); + + @Accessor("grassColorModifier") + BiomeEffects.GrassColorModifier getGrassColorModifier(); +} 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/access/GeneratorTypeAccessor.java similarity index 74% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/GeneratorTypeAccessor.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/GeneratorTypeAccessor.java index 07449ae3a..bd315cc54 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/access/GeneratorTypeAccessor.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.fabric.mixin; +package com.dfsek.terra.fabric.mixin.access; import net.minecraft.client.world.GeneratorType; import net.minecraft.text.Text; @@ -10,12 +10,12 @@ import java.util.List; @Mixin(GeneratorType.class) public interface GeneratorTypeAccessor { - @Accessor - static List getVALUES() { + @Accessor("VALUES") + static List getValues() { throw new UnsupportedOperationException(); } @Mutable - @Accessor + @Accessor("translationKey") void setTranslationKey(Text translationKey); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/MobSpawnerLogicAccessor.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/MobSpawnerLogicAccessor.java new file mode 100644 index 000000000..4b7eb1f4f --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/MobSpawnerLogicAccessor.java @@ -0,0 +1,12 @@ +package com.dfsek.terra.fabric.mixin.access; + +import net.minecraft.util.Identifier; +import net.minecraft.world.MobSpawnerLogic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(MobSpawnerLogic.class) +public interface MobSpawnerLogicAccessor { + @Invoker("getEntityId") + Identifier callGetEntityId(); +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/StateAccessor.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/StateAccessor.java new file mode 100644 index 000000000..8518443af --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/StateAccessor.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.fabric.mixin.access; + +import net.minecraft.state.State; +import net.minecraft.state.property.Property; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Map; +import java.util.function.Function; + +@Mixin(State.class) +public interface StateAccessor { + @Accessor("PROPERTY_MAP_PRINTER") + static Function, Comparable>, String> getPropertyMapPrinter() { + throw new UnsupportedOperationException(); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/BiomeMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/BiomeMixin.java new file mode 100644 index 000000000..ab3bff88a --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/BiomeMixin.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.fabric.mixin.implementations; + +import net.minecraft.world.biome.Biome; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(Biome.class) +@Implements(@Interface(iface = com.dfsek.terra.api.platform.world.Biome.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class BiomeMixin { + public Object terra$getHandle() { + return this; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/ChunkGeneratorMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/ChunkGeneratorMixin.java new file mode 100644 index 000000000..b766f4692 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/ChunkGeneratorMixin.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.fabric.mixin.implementations; + +import net.minecraft.world.gen.chunk.ChunkGenerator; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ChunkGenerator.class) +@Implements(@Interface(iface = com.dfsek.terra.api.platform.world.generator.ChunkGenerator.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ChunkGeneratorMixin { + public Object terra$getHandle() { + return this; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/ConfiguredFeatureMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/ConfiguredFeatureMixin.java new file mode 100644 index 000000000..0398a2d4c --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/ConfiguredFeatureMixin.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.fabric.mixin.implementations; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.api.util.collections.MaterialSet; +import com.dfsek.terra.fabric.TerraFabricPlugin; +import com.dfsek.terra.profiler.ProfileFrame; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.world.StructureWorldAccess; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.gen.feature.ConfiguredFeature; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Locale; +import java.util.Random; + +@Mixin(ConfiguredFeature.class) +@Implements(@Interface(iface = Tree.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ConfiguredFeatureMixin { + @Shadow + public abstract boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos); + + @SuppressWarnings({"ConstantConditions", "try"}) + public boolean terra$plant(Location l, Random r) { + String id = BuiltinRegistries.CONFIGURED_FEATURE.getId((ConfiguredFeature) (Object) this).toString(); + try(ProfileFrame ignore = TerraFabricPlugin.getInstance().getProfiler().profile("fabric_tree:" + id.toLowerCase(Locale.ROOT))) { + StructureWorldAccess fabricWorldAccess = ((StructureWorldAccess) l.getWorld()); + ChunkGenerator generatorWrapper = (ChunkGenerator) l.getWorld().getGenerator(); + return generate(fabricWorldAccess, generatorWrapper, r, new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ())); + } + } + + public MaterialSet terra$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/mixin/implementations/block/BlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockEntityMixin.java new file mode 100644 index 000000000..8672f444d --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockEntityMixin.java @@ -0,0 +1,60 @@ +package com.dfsek.terra.fabric.mixin.implementations.block; + +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.FabricAdapter; +import com.dfsek.terra.fabric.block.FabricBlock; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(BlockEntity.class) +@Implements(@Interface(iface = BlockState.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class BlockEntityMixin { + @Shadow + protected BlockPos pos; + @Shadow + @Nullable + protected World world; + + @Shadow + public abstract net.minecraft.block.BlockState getCachedState(); + + @Shadow + public abstract boolean hasWorld(); + + public Object terra$getHandle() { + return this; + } + + public Block terra$getBlock() { + return new FabricBlock(pos, world); + } + + public int terra$getX() { + return pos.getX(); + } + + public int terra$getY() { + return pos.getY(); + } + + public int terra$getZ() { + return pos.getZ(); + } + + public BlockData terra$getBlockData() { + return FabricAdapter.adapt(getCachedState()); + } + + public boolean terra$update(boolean applyPhysics) { + if(hasWorld()) world.getChunk(pos).setBlockEntity(pos, (BlockEntity) (Object) this); + return true; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockMixin.java new file mode 100644 index 000000000..0875cab40 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockMixin.java @@ -0,0 +1,36 @@ +package com.dfsek.terra.fabric.mixin.implementations.block; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockType; +import com.dfsek.terra.fabric.FabricAdapter; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(Block.class) +@Implements(@Interface(iface = BlockType.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class BlockMixin { + @Shadow + private BlockState defaultState; + + public Object terra$getHandle() { + return this; + } + + public BlockData terra$getDefaultData() { + return FabricAdapter.adapt(defaultState); + } + + public boolean terra$isSolid() { + return defaultState.isOpaque(); + } + + @SuppressWarnings("ConstantConditions") + public boolean terra$isWater() { + return ((Object) this) == Blocks.WATER; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/LootableContainerBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/LootableContainerBlockEntityMixin.java new file mode 100644 index 000000000..9bb319856 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/LootableContainerBlockEntityMixin.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.fabric.mixin.implementations.block.state; + +import com.dfsek.terra.api.platform.block.state.Container; +import com.dfsek.terra.api.platform.inventory.Inventory; +import com.dfsek.terra.fabric.mixin.implementations.block.BlockEntityMixin; +import net.minecraft.block.entity.LootableContainerBlockEntity; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(LootableContainerBlockEntity.class) +@Implements(@Interface(iface = Container.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class LootableContainerBlockEntityMixin extends BlockEntityMixin { + public Inventory terra$getInventory() { + return (Inventory) this; + } + + public Object terra$getHandle() { + return this; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/MobSpawnerBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/MobSpawnerBlockEntityMixin.java new file mode 100644 index 000000000..8f664787e --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/MobSpawnerBlockEntityMixin.java @@ -0,0 +1,119 @@ +package com.dfsek.terra.fabric.mixin.implementations.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.mixin.access.MobSpawnerLogicAccessor; +import net.minecraft.block.entity.MobSpawnerBlockEntity; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.MobSpawnerLogic; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(MobSpawnerBlockEntity.class) +@Implements(@Interface(iface = MobSpawner.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class MobSpawnerBlockEntityMixin { + @Shadow + public abstract MobSpawnerLogic getLogic(); + + public EntityType terra$getSpawnedType() { + return (EntityType) Registry.ENTITY_TYPE.get(((MobSpawnerLogicAccessor) getLogic()).callGetEntityId()); + } + + public void terra$setSpawnedType(@NotNull EntityType creatureType) { + getLogic().setEntityId((net.minecraft.entity.EntityType) creatureType); + } + + public int terra$getDelay() { + return 0; + } + + public void terra$setDelay(int delay) { + + } + + public int terra$getMinSpawnDelay() { + return 0; + } + + public void terra$setMinSpawnDelay(int delay) { + + } + + public int terra$getMaxSpawnDelay() { + return 0; + } + + public void terra$setMaxSpawnDelay(int delay) { + + } + + public int terra$getSpawnCount() { + return 0; + } + + public void terra$setSpawnCount(int spawnCount) { + + } + + public int terra$getMaxNearbyEntities() { + return 0; + } + + public void terra$setMaxNearbyEntities(int maxNearbyEntities) { + + } + + public int terra$getRequiredPlayerRange() { + return 0; + } + + public void terra$setRequiredPlayerRange(int requiredPlayerRange) { + + } + + public int terra$getSpawnRange() { + return 0; + } + + public void terra$setSpawnRange(int spawnRange) { + + } + + public void terra$applyState(String state) { + SerialState.parse(state).forEach((k, v) -> { + switch(k) { + case "type": + terra$setSpawnedType(TerraFabricPlugin.getInstance().getWorldHandle().getEntity(v)); + return; + case "delay": + terra$setDelay(Integer.parseInt(v)); + return; + case "min_delay": + terra$setMinSpawnDelay(Integer.parseInt(v)); + return; + case "max_delay": + terra$setMaxSpawnDelay(Integer.parseInt(v)); + return; + case "spawn_count": + terra$setSpawnCount(Integer.parseInt(v)); + return; + case "spawn_range": + terra$setSpawnRange(Integer.parseInt(v)); + return; + case "max_nearby": + terra$setMaxNearbyEntities(Integer.parseInt(v)); + return; + case "required_player_range": + terra$setRequiredPlayerRange(Integer.parseInt(v)); + return; + default: + throw new IllegalArgumentException("Invalid property: " + k); + } + }); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/SignBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/SignBlockEntityMixin.java new file mode 100644 index 000000000..f8ab0ee3f --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/SignBlockEntityMixin.java @@ -0,0 +1,47 @@ +package com.dfsek.terra.fabric.mixin.implementations.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.text.Text; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(SignBlockEntity.class) +@Implements(@Interface(iface = Sign.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class SignBlockEntityMixin { + @Shadow + public abstract void setTextOnRow(int row, Text text); + + @Shadow + @Final + private Text[] text; + + public @NotNull String[] terra$getLines() { + String[] lines = new String[text.length]; + for(int i = 0; i < text.length; i++) { + lines[i] = text[i].asString(); + } + return lines; + } + + public @NotNull String terra$getLine(int index) throws IndexOutOfBoundsException { + return text[index].asString(); + } + + public void terra$setLine(int index, @NotNull String line) throws IndexOutOfBoundsException { + setTextOnRow(index, new LiteralText(line)); + } + + public void terra$applyState(String state) { + SerialState.parse(state).forEach((k, v) -> { + if(!k.startsWith("text")) throw new IllegalArgumentException("Invalid property: " + k); + terra$setLine(Integer.parseInt(k.substring(4)), v); + }); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/ChunkRegionMixin.java new file mode 100644 index 000000000..55ebe0576 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/ChunkRegionMixin.java @@ -0,0 +1,57 @@ +package com.dfsek.terra.fabric.mixin.implementations.chunk; + +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.fabric.block.FabricBlock; +import com.dfsek.terra.fabric.block.FabricBlockData; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.ChunkRegion; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ChunkRegion.class) +@Implements(@Interface(iface = Chunk.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ChunkRegionMixin { + @Final + @Shadow + private int centerChunkX; + + @Final + @Shadow + private int centerChunkZ; + + public int terra$getX() { + return centerChunkX; + } + + public int terra$getZ() { + return centerChunkZ; + } + + public World terra$getWorld() { + return (World) this; + } + + public Block terra$getBlock(int x, int y, int z) { + BlockPos pos = new BlockPos(x + (centerChunkX << 4), y, z + (centerChunkZ << 4)); + return new FabricBlock(pos, (ChunkRegion) (Object) this); + } + + public @NotNull BlockData terra$getBlockData(int x, int y, int z) { + return terra$getBlock(x, y, z).getBlockData(); + } + + public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) { + ((ChunkRegion) (Object) this).setBlockState(new BlockPos(x + (centerChunkX << 4), y, z + (centerChunkZ << 4)), ((FabricBlockData) blockData).getHandle(), 0); + } + + public Object terra$getHandle() { + return this; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/WorldChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/WorldChunkMixin.java new file mode 100644 index 000000000..c09e52dc3 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/WorldChunkMixin.java @@ -0,0 +1,53 @@ +package com.dfsek.terra.fabric.mixin.implementations.chunk; + +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.fabric.block.FabricBlock; +import com.dfsek.terra.fabric.block.FabricBlockData; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.WorldChunk; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(WorldChunk.class) +@Implements(@Interface(iface = Chunk.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class WorldChunkMixin { + @Final + @Shadow + private net.minecraft.world.World world; + + public int terra$getX() { + return ((net.minecraft.world.chunk.Chunk) this).getPos().x; + } + + public int terra$getZ() { + return ((net.minecraft.world.chunk.Chunk) this).getPos().z; + } + + public World terra$getWorld() { + return (World) world; + } + + public Block terra$getBlock(int x, int y, int z) { + BlockPos pos = new BlockPos(x + (terra$getX() << 4), y, z + (terra$getZ() << 4)); + return new FabricBlock(pos, world); + } + + public @NotNull BlockData terra$getBlockData(int x, int y, int z) { + return terra$getBlock(x, y, z).getBlockData(); + } + + public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) { + ((net.minecraft.world.chunk.Chunk) this).setBlockState(new BlockPos(x, y, z), ((FabricBlockData) blockData).getHandle(), false); + } + + public Object terra$getHandle() { + return this; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java new file mode 100644 index 000000000..15a862bed --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java @@ -0,0 +1,36 @@ +package com.dfsek.terra.fabric.mixin.implementations.chunk.data; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.world.generator.ChunkData; +import com.dfsek.terra.fabric.block.FabricBlockData; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.ProtoChunk; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ProtoChunk.class) +@Implements(@Interface(iface = ChunkData.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ProtoChunkMixin { + @Shadow + public abstract BlockState getBlockState(BlockPos pos); + + public @NotNull BlockData terra$getBlockData(int x, int y, int z) { + return new FabricBlockData(getBlockState(new BlockPos(x, y, z))); + } + + public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) { + ((net.minecraft.world.chunk.Chunk) this).setBlockState(new BlockPos(x, y, z), ((FabricBlockData) blockData).getHandle(), false); + } + + public Object terra$getHandle() { + return this; + } + + public int terra$getMaxHeight() { + return 255; // TODO: 1.17 - Implement dynamic height. + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityMixin.java new file mode 100644 index 000000000..88d6bfbb6 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityMixin.java @@ -0,0 +1,51 @@ +package com.dfsek.terra.fabric.mixin.implementations.entity; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.fabric.FabricAdapter; +import net.minecraft.entity.Entity; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import net.minecraft.util.math.BlockPos; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.UUID; + +@Mixin(Entity.class) +@Implements(@Interface(iface = com.dfsek.terra.api.platform.entity.Entity.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class EntityMixin { + @Shadow + public net.minecraft.world.World world; + + @Shadow + private BlockPos blockPos; + + @Shadow + public abstract void teleport(double destX, double destY, double destZ); + + @Shadow + public abstract void sendSystemMessage(Text message, UUID senderUuid); + + public Object terra$getHandle() { + return this; + } + + public Location terra$getLocation() { + return new Location((World) world, FabricAdapter.adapt(blockPos)); + } + + public void terra$setLocation(Location location) { + teleport(location.getX(), location.getY(), location.getZ()); + } + + public World terra$getWorld() { + return (World) world; + } + + public void terra$sendMessage(String message) { + sendSystemMessage(new LiteralText(message), UUID.randomUUID()); // TODO: look into how this actually works and make it less jank + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityTypeMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityTypeMixin.java new file mode 100644 index 000000000..ee0cbc0cf --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityTypeMixin.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.fabric.mixin.implementations.entity; + +import net.minecraft.entity.EntityType; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(EntityType.class) +@Implements(@Interface(iface = com.dfsek.terra.api.platform.entity.EntityType.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class EntityTypeMixin { + public Object terra$getHandle() { + return this; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/PlayerEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/PlayerEntityMixin.java new file mode 100644 index 000000000..b4bf0d35e --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/PlayerEntityMixin.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.fabric.mixin.implementations.entity; + +import com.dfsek.terra.api.platform.entity.Player; +import net.minecraft.entity.player.PlayerEntity; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(PlayerEntity.class) +@Implements(@Interface(iface = Player.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class PlayerEntityMixin extends EntityMixin { + +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/ServerCommandSourceMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/ServerCommandSourceMixin.java new file mode 100644 index 000000000..caf9b91f1 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/ServerCommandSourceMixin.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.fabric.mixin.implementations.entity; + +import com.dfsek.terra.api.platform.CommandSender; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ServerCommandSource.class) +@Implements(@Interface(iface = CommandSender.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ServerCommandSourceMixin { + @Shadow + public abstract void sendFeedback(Text message, boolean broadcastToOps); + + public void terra$sendMessage(String message) { + sendFeedback(new LiteralText(message), true); + } + + public Object terra$getHandle() { + return this; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/LockableContainerBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/LockableContainerBlockEntityMixin.java new file mode 100644 index 000000000..1c14e2ab5 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/LockableContainerBlockEntityMixin.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.fabric.mixin.implementations.inventory; + +import com.dfsek.terra.api.platform.inventory.Inventory; +import com.dfsek.terra.api.platform.inventory.ItemStack; +import net.minecraft.block.entity.LockableContainerBlockEntity; +import net.minecraft.item.Items; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(LockableContainerBlockEntity.class) +@Implements(@Interface(iface = Inventory.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public class LockableContainerBlockEntityMixin { + public Object terra$getHandle() { + return this; + } + + public int terra$getSize() { + return ((LockableContainerBlockEntity) (Object) this).size(); + } + + @SuppressWarnings("ConstantConditions") + public ItemStack terra$getItem(int slot) { + net.minecraft.item.ItemStack itemStack = ((LockableContainerBlockEntity) (Object) this).getStack(slot); + return itemStack.getItem() == Items.AIR ? null : (ItemStack) (Object) itemStack; + } + + @SuppressWarnings("ConstantConditions") + public void terra$setItem(int slot, ItemStack newStack) { + ((LockableContainerBlockEntity) (Object) this).setStack(slot, (net.minecraft.item.ItemStack) (Object) newStack); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemMixin.java new file mode 100644 index 000000000..b8f7a9be1 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemMixin.java @@ -0,0 +1,28 @@ +package com.dfsek.terra.fabric.mixin.implementations.inventory.item; + +import com.dfsek.terra.api.platform.inventory.ItemStack; +import net.minecraft.item.Item; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(Item.class) +@Implements(@Interface(iface = com.dfsek.terra.api.platform.inventory.Item.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ItemMixin { + @Shadow + public abstract int getMaxDamage(); + + public Object terra$getHandle() { + return this; + } + + @SuppressWarnings("ConstantConditions") + public ItemStack terra$newItemStack(int amount) { + return (ItemStack) (Object) new net.minecraft.item.ItemStack((Item) (Object) this, amount); + } + + public double terra$getMaxDurability() { + return getMaxDamage(); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemStackMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemStackMixin.java new file mode 100644 index 000000000..55fe05f26 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemStackMixin.java @@ -0,0 +1,61 @@ +package com.dfsek.terra.fabric.mixin.implementations.inventory.item; + +import com.dfsek.terra.api.platform.inventory.Item; +import com.dfsek.terra.api.platform.inventory.item.ItemMeta; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ItemStack.class) +@Implements(@Interface(iface = com.dfsek.terra.api.platform.inventory.ItemStack.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ItemStackMixin { + @Shadow + public abstract int getCount(); + + @Shadow + public abstract void setCount(int count); + + @Shadow + public abstract net.minecraft.item.Item getItem(); + + @Shadow + public abstract boolean isDamageable(); + + @Shadow + public abstract void setTag(@Nullable CompoundTag tag); + + public int terra$getAmount() { + return getCount(); + } + + public void terra$setAmount(int i) { + setCount(i); + } + + public Item terra$getType() { + return (Item) getItem(); + } + + public ItemMeta terra$getItemMeta() { + return (ItemMeta) this; + } + + @SuppressWarnings("ConstantConditions") + public void terra$setItemMeta(ItemMeta meta) { + setTag(((ItemStack) (Object) meta).getTag()); + } + + public Object terra$getHandle() { + return this; + } + + @Intrinsic + public boolean terra$isDamageable() { + return isDamageable(); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/EnchantmentMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/EnchantmentMixin.java new file mode 100644 index 000000000..5fd30638d --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/EnchantmentMixin.java @@ -0,0 +1,38 @@ +package com.dfsek.terra.fabric.mixin.implementations.inventory.meta; + +import com.dfsek.terra.api.platform.inventory.ItemStack; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.util.registry.Registry; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Objects; + +@Mixin(Enchantment.class) +@Implements(@Interface(iface = com.dfsek.terra.api.platform.inventory.item.Enchantment.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class EnchantmentMixin { + @Shadow + public abstract boolean isAcceptableItem(net.minecraft.item.ItemStack stack); + + @Shadow + public abstract boolean canCombine(Enchantment other); + + public Object terra$getHandle() { + return this; + } + + @SuppressWarnings("ConstantConditions") + public boolean terra$canEnchantItem(ItemStack itemStack) { + return isAcceptableItem((net.minecraft.item.ItemStack) (Object) itemStack); + } + + public String terra$getID() { + return Objects.requireNonNull(Registry.ENCHANTMENT.getId((Enchantment) (Object) this)).toString(); + } + + public boolean terra$conflictsWith(com.dfsek.terra.api.platform.inventory.item.Enchantment other) { + return !canCombine((Enchantment) other); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackDamageableMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackDamageableMixin.java new file mode 100644 index 000000000..0d3a2fd06 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackDamageableMixin.java @@ -0,0 +1,36 @@ +package com.dfsek.terra.fabric.mixin.implementations.inventory.meta; + +import com.dfsek.terra.api.platform.inventory.item.Damageable; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ItemStack.class) +@Implements(@Interface(iface = Damageable.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ItemStackDamageableMixin { + @Shadow + public abstract boolean isDamaged(); + + @Shadow + public abstract int getDamage(); + + @Shadow + public abstract void setDamage(int damage); + + public boolean terra$hasDamage() { + return isDamaged(); + } + + @Intrinsic + public void terra$setDamage(int damage) { + setDamage(damage); + } + + @Intrinsic + public int terra$getDamage() { + return getDamage(); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackMetaMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackMetaMixin.java new file mode 100644 index 000000000..56efedc53 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackMetaMixin.java @@ -0,0 +1,50 @@ +package com.dfsek.terra.fabric.mixin.implementations.inventory.meta; + +import com.dfsek.terra.api.platform.inventory.item.Enchantment; +import com.dfsek.terra.api.platform.inventory.item.ItemMeta; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.util.registry.Registry; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +@Mixin(ItemStack.class) +@Implements(@Interface(iface = ItemMeta.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ItemStackMetaMixin { + @Shadow + public abstract boolean hasEnchantments(); + + @Shadow + public abstract ListTag getEnchantments(); + + @Shadow + public abstract void addEnchantment(net.minecraft.enchantment.Enchantment enchantment, int level); + + public Object terra$getHandle() { + return this; + } + + @Intrinsic(displace = true) + public Map terra$getEnchantments() { + if(!hasEnchantments()) return Collections.emptyMap(); + Map map = new HashMap<>(); + + getEnchantments().forEach(enchantment -> { + CompoundTag eTag = (CompoundTag) enchantment; + map.put((Enchantment) Registry.ENCHANTMENT.get(eTag.getInt("id")), eTag.getInt("lvl")); + }); + return map; + } + + public void terra$addEnchantment(Enchantment enchantment, int level) { + addEnchantment((net.minecraft.enchantment.Enchantment) enchantment, level); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/package-info.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/package-info.java new file mode 100644 index 000000000..ec0453641 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/package-info.java @@ -0,0 +1,5 @@ +/** + * Mixins in this package implement Terra + * interfaces in Minecraft classes. + */ +package com.dfsek.terra.fabric.mixin.implementations; \ No newline at end of file diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java new file mode 100644 index 000000000..d87799f57 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java @@ -0,0 +1,109 @@ +package com.dfsek.terra.fabric.mixin.implementations.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.api.platform.world.generator.GeneratorWrapper; +import com.dfsek.terra.api.world.generation.TerraChunkGenerator; +import com.dfsek.terra.fabric.block.FabricBlock; +import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.ChunkRegion; +import net.minecraft.world.ServerWorldAccess; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ChunkRegion.class) +@Implements(@Interface(iface = World.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ChunkRegionMixin { + @Shadow + @Final + private ServerWorld world; + + @Shadow + @Final + private long seed; + + public int terra$getMaxHeight() { + return ((ChunkRegion) (Object) this).getDimensionHeight(); + } + + @SuppressWarnings("deprecation") + public ChunkGenerator terra$getGenerator() { + return (ChunkGenerator) ((ChunkRegion) (Object) this).toServerWorld().getChunkManager().getChunkGenerator(); + } + + public Chunk terra$getChunkAt(int x, int z) { + return (Chunk) ((ChunkRegion) (Object) this).getChunk(x, z); + } + + public Block terra$getBlockAt(int x, int y, int z) { + return new FabricBlock(new BlockPos(x, y, z), ((ChunkRegion) (Object) this)); + } + + @SuppressWarnings("deprecation") + public Entity terra$spawnEntity(Location location, EntityType entityType) { + net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(((ChunkRegion) (Object) this).toServerWorld()); + entity.setPos(location.getX(), location.getY(), location.getZ()); + ((ChunkRegion) (Object) this).spawnEntity(entity); + return (Entity) entity; + } + + @Intrinsic + public long terra$getSeed() { + return seed; + } + + public int terra$getMinHeight() { + return 0; + } + + public Object terra$getHandle() { + return this; + } + + public boolean terra$isTerraWorld() { + return terra$getGenerator() instanceof GeneratorWrapper; + } + + public TerraChunkGenerator terra$getTerraGenerator() { + return ((FabricChunkGeneratorWrapper) terra$getGenerator()).getHandle(); + } + + /** + * We need regions delegating to the same world + * to have the same hashcode. This + * minimizes cache misses. + *

+ * This is sort of jank, but shouldn't(tm) + * break any other mods, unless they're doing + * something they really shouldn't, since + * ChunkRegions are not supposed to persist. + */ + @Override + public int hashCode() { + return world.hashCode(); + } + + /** + * Overridden in the same manner as {@link #hashCode()} + * + * @param other Another object + * @return Whether this world is the same as other. + * @see #hashCode() + */ + @Override + public boolean equals(Object other) { + if(!(other instanceof ServerWorldAccess)) return false; + return world.equals(((ServerWorldAccess) other).toServerWorld()); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ServerWorldMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ServerWorldMixin.java new file mode 100644 index 000000000..15a5c8138 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ServerWorldMixin.java @@ -0,0 +1,86 @@ +package com.dfsek.terra.fabric.mixin.implementations.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.api.platform.world.generator.GeneratorWrapper; +import com.dfsek.terra.api.world.generation.TerraChunkGenerator; +import com.dfsek.terra.fabric.block.FabricBlock; +import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.ServerWorldAccess; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ServerWorld.class) +@Implements(@Interface(iface = World.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ServerWorldMixin { + @Shadow + public abstract long getSeed(); + + public int terra$getMaxHeight() { + return ((ServerWorld) (Object) this).getDimensionHeight(); + } + + public ChunkGenerator terra$getGenerator() { + return (ChunkGenerator) ((ServerWorld) (Object) this).getChunkManager().getChunkGenerator(); + } + + public Chunk terra$getChunkAt(int x, int z) { + return (Chunk) ((ServerWorld) (Object) this).getChunk(x, z); + } + + public Block terra$getBlockAt(int x, int y, int z) { + return new FabricBlock(new BlockPos(x, y, z), ((ServerWorld) (Object) this)); + } + + public Entity terra$spawnEntity(Location location, EntityType entityType) { + net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(((ServerWorld) (Object) this)); + entity.setPos(location.getX(), location.getY(), location.getZ()); + ((ServerWorld) (Object) this).spawnEntity(entity); + return (Entity) entity; + } + + @Intrinsic + public long terra$getSeed() { + return getSeed(); + } + + public int terra$getMinHeight() { + return 0; + } + + public Object terra$getHandle() { + return this; + } + + public boolean terra$isTerraWorld() { + return terra$getGenerator() instanceof GeneratorWrapper; + } + + public TerraChunkGenerator terra$getTerraGenerator() { + return ((FabricChunkGeneratorWrapper) terra$getGenerator()).getHandle(); + } + + /** + * Overridden in the same manner as {@link ChunkRegionMixin#hashCode()} + * + * @param other Another object + * @return Whether this world is the same as other. + * @see ChunkRegionMixin#hashCode() + */ + @SuppressWarnings("ConstantConditions") + @Override + public boolean equals(Object other) { + if(!(other instanceof ServerWorldAccess)) return false; + return (ServerWorldAccess) this == (((ServerWorldAccess) other).toServerWorld()); + } +} 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 deleted file mode 100644 index e151013f0..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricAdapter.java +++ /dev/null @@ -1,127 +0,0 @@ -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/FabricTree.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricTree.java index c8415ad1b..e69de29bb 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,40 +0,0 @@ -package com.dfsek.terra.fabric.world; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.api.util.collections.MaterialSet; -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.profiler.ProfileFrame; -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.Locale; -import java.util.Random; - -public class FabricTree implements Tree { - private final ConfiguredFeature delegate; - - public FabricTree(ConfiguredFeature delegate) { - this.delegate = delegate; - } - - @Override - public boolean plant(Location l, Random r) { - try(ProfileFrame ignore = TerraFabricPlugin.getInstance().getProfiler().profile("fabric_tree:" + delegate.toString().toLowerCase(Locale.ROOT))) { - FabricWorldAccess fabricWorldAccess = ((FabricWorldAccess) l.getWorld()); - ChunkGenerator generatorWrapper = ((FabricChunkGenerator) fabricWorldAccess.getGenerator()).getHandle(); - return delegate.generate((StructureWorldAccess) fabricWorldAccess.getHandle(), generatorWrapper, r, new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ())); - } - } - - @Override - 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/block/state/FabricBlockState.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricBlockState.java deleted file mode 100644 index d0dbf5bf4..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricBlockState.java +++ /dev/null @@ -1,73 +0,0 @@ -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 deleted file mode 100644 index 743c06d83..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricContainer.java +++ /dev/null @@ -1,18 +0,0 @@ -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/entity/FabricCommandSender.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricCommandSender.java deleted file mode 100644 index e7f946008..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricCommandSender.java +++ /dev/null @@ -1,23 +0,0 @@ -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 deleted file mode 100644 index 65c26849d..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricEntity.java +++ /dev/null @@ -1,43 +0,0 @@ -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/FabricPlayer.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricPlayer.java deleted file mode 100644 index 143ad024c..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricPlayer.java +++ /dev/null @@ -1,42 +0,0 @@ -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/generator/FabricChunkGenerator.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGenerator.java deleted file mode 100644 index ae7526326..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGenerator.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.fabric.world.generator; - -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; - -public class FabricChunkGenerator implements ChunkGenerator { - private final net.minecraft.world.gen.chunk.ChunkGenerator delegate; - - public FabricChunkGenerator(net.minecraft.world.gen.chunk.ChunkGenerator delegate) { - this.delegate = delegate; - } - - @Override - public net.minecraft.world.gen.chunk.ChunkGenerator getHandle() { - return delegate; - } -} 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 deleted file mode 100644 index 05b1dbb1e..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricSeededWorldAccess.java +++ /dev/null @@ -1,133 +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.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, FabricWorldHandle { - - private final Handle handle; - - public FabricSeededWorldAccess(WorldAccess access, long seed, net.minecraft.world.gen.chunk.ChunkGenerator generator) { - this.handle = new Handle(access, seed, generator); - } - - @Override - public long getSeed() { - return handle.getSeed(); - } - - @Override - public int getMaxHeight() { - return handle.getWorldAccess().getDimensionHeight(); - } - - @Override - public ChunkGenerator getGenerator() { - return new FabricChunkGenerator(handle.getGenerator()); - } - - @Override - public String getName() { - return handle.toString(); // TODO: implementation - } - - @Override - public UUID getUID() { - return UUID.randomUUID(); // TODO: implementation - } - - @Override - public boolean isChunkGenerated(int x, int z) { - return false; - } - - @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, handle.worldAccess); - } - - @Override - 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 int getMinHeight() { - return 0; - } - - @Override - public int hashCode() { - return ((ServerWorldAccess) handle.worldAccess).toServerWorld().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if(!(obj instanceof FabricSeededWorldAccess)) return false; - return ((ServerWorldAccess) ((FabricSeededWorldAccess) obj).handle.worldAccess).toServerWorld().equals(((ServerWorldAccess) handle.worldAccess).toServerWorld()); - } - - @Override - public Handle getHandle() { - return handle; - } - - @Override - public WorldAccess getWorld() { - return handle.worldAccess; - } - - public static class Handle { - private final WorldAccess worldAccess; - private final long seed; - private final net.minecraft.world.gen.chunk.ChunkGenerator generator; - - public Handle(WorldAccess worldAccess, long seed, net.minecraft.world.gen.chunk.ChunkGenerator generator) { - this.worldAccess = worldAccess; - this.seed = seed; - this.generator = generator; - } - - public net.minecraft.world.gen.chunk.ChunkGenerator getGenerator() { - return generator; - } - - public long getSeed() { - return seed; - } - - public WorldAccess getWorldAccess() { - return worldAccess; - } - } -} 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 deleted file mode 100644 index 8cb464353..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldAccess.java +++ /dev/null @@ -1,108 +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.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; -import net.minecraft.world.StructureWorldAccess; -import net.minecraft.world.WorldAccess; - -import java.io.File; -import java.util.UUID; - -public class FabricWorldAccess implements World, FabricWorldHandle { - private final WorldAccess delegate; - - public FabricWorldAccess(WorldAccess delegate) { - this.delegate = delegate; - } - - @Override - public long getSeed() { - return ((StructureWorldAccess) delegate).getSeed(); - } - - @Override - public int getMaxHeight() { - return delegate.getDimensionHeight(); - } - - @Override - public ChunkGenerator getGenerator() { - return new FabricChunkGenerator(((ServerWorldAccess) delegate).toServerWorld().getChunkManager().getChunkGenerator()); - } - - @Override - public String getName() { - return ((ServerWorldAccess) delegate).toServerWorld().worldProperties.getLevelName(); - } - - @Override - public UUID getUID() { - return null; - } - - @Override - public boolean isChunkGenerated(int x, int z) { - return false; - } - - @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); - } - - @Override - 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 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/FabricWorldHandle.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldHandle.java deleted file mode 100644 index 7565201aa..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldHandle.java +++ /dev/null @@ -1,7 +0,0 @@ -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 deleted file mode 100644 index 8dbf41449..000000000 --- a/platforms/fabric/src/main/resources/terra-refmap.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "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 fcf59a730..f7a4eba9a 100644 --- a/platforms/fabric/src/main/resources/terra.accesswidener +++ b/platforms/fabric/src/main/resources/terra.accesswidener @@ -1,19 +1,3 @@ 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; - -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; +extendable method net/minecraft/client/world/GeneratorType (Ljava/lang/String;)V \ No newline at end of file diff --git a/platforms/fabric/src/main/resources/terra.mixins.json b/platforms/fabric/src/main/resources/terra.mixins.json index 8537843c7..394dd3742 100644 --- a/platforms/fabric/src/main/resources/terra.mixins.json +++ b/platforms/fabric/src/main/resources/terra.mixins.json @@ -4,9 +4,36 @@ "package": "com.dfsek.terra.fabric.mixin", "compatibilityLevel": "JAVA_8", "mixins": [ + "GeneratorOptionsMixin", + "access.BiomeEffectsAccessor", + "access.MobSpawnerLogicAccessor", + "access.StateAccessor", + "implementations.BiomeMixin", + "implementations.ChunkGeneratorMixin", + "implementations.ConfiguredFeatureMixin", + "implementations.block.BlockEntityMixin", + "implementations.block.BlockMixin", + "implementations.block.state.LootableContainerBlockEntityMixin", + "implementations.block.state.MobSpawnerBlockEntityMixin", + "implementations.block.state.SignBlockEntityMixin", + "implementations.chunk.ChunkRegionMixin", + "implementations.chunk.WorldChunkMixin", + "implementations.chunk.data.ProtoChunkMixin", + "implementations.entity.EntityMixin", + "implementations.entity.EntityTypeMixin", + "implementations.entity.PlayerEntityMixin", + "implementations.entity.ServerCommandSourceMixin", + "implementations.inventory.LockableContainerBlockEntityMixin", + "implementations.inventory.item.ItemMixin", + "implementations.inventory.item.ItemStackMixin", + "implementations.inventory.meta.EnchantmentMixin", + "implementations.inventory.meta.ItemStackDamageableMixin", + "implementations.inventory.meta.ItemStackMetaMixin", + "implementations.world.ChunkRegionMixin", + "implementations.world.ServerWorldMixin" ], "client": [ - "GeneratorTypeAccessor" + "access.GeneratorTypeAccessor" ], "server": [], "injectors": { diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts new file mode 100644 index 000000000..2bfb7ad0e --- /dev/null +++ b/platforms/forge/build.gradle.kts @@ -0,0 +1,136 @@ +import com.dfsek.terra.configureCommon +import net.minecraftforge.gradle.common.util.RunConfig +import net.minecraftforge.gradle.mcp.task.GenerateSRG +import net.minecraftforge.gradle.userdev.UserDevExtension +import net.minecraftforge.gradle.userdev.tasks.RenameJarInPlace + +buildscript { + repositories { + maven { url = uri("https://files.minecraftforge.net/maven") } + jcenter() + mavenCentral() + maven { url = uri("https://repo.spongepowered.org/repository/maven-public/") } + } + dependencies { + classpath(group = "net.minecraftforge.gradle", name = "ForgeGradle", version = "4.1.+") + classpath("org.spongepowered:mixingradle:0.7-SNAPSHOT") + } +} +apply(plugin = "net.minecraftforge.gradle") +apply(plugin = "org.spongepowered.mixin") + +configure { + add(sourceSets.main.get(), "terra-refmap.json") +} + +plugins { + java + id("com.modrinth.minotaur").version("1.1.0") +} + +configureCommon() + +group = "com.dfsek.terra.forge" + +repositories { + maven { url = uri("https://files.minecraftforge.net/maven") } + jcenter() + mavenCentral() + maven { url = uri("https://repo.spongepowered.org/repository/maven-public/") } +} + +val forgeVersion = "36.1.13" +val mcVersion = "1.16.5" +dependencies { + "shadedApi"(project(":common")) + "minecraft"("net.minecraftforge:forge:$mcVersion-$forgeVersion") + "annotationProcessor"("org.spongepowered:mixin:0.8.2:processor") +} + +if ("true" == System.getProperty("idea.sync.active")) { + afterEvaluate { + tasks.withType().all { + options.annotationProcessorPath = files() + } + } +} + +afterEvaluate { + val reobf = extensions.getByName>("reobf") + reobf.maybeCreate("shadowJar").run { + group = "forge" + mappings = tasks.getByName("createMcpToSrg").output + } +} + +configure { + mappings(mapOf( + "channel" to "official", + "version" to mcVersion + )) + runs { + val runConfig = Action { + properties(mapOf( + "forge.logging.markers" to "SCAN,REGISTRIES,REGISTRYDUMP", + "forge.logging.console.level" to "debug" + )) + arg("-mixin.config=terra.mixins.json") + workingDirectory = project.file("run").canonicalPath + source(sourceSets["main"]) + } + create("client", runConfig) + create("server", runConfig) + } +} + +tasks.register("deobfJar") { + from(sourceSets["main"].output) + archiveClassifier.set("dev") + group = "forge" +} + +val deobfElements = configurations.register("deobfElements") { + isVisible = false + description = "De-obfuscated elements for libs" + isCanBeResolved = false + isCanBeConsumed = true + attributes { + attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_API)) + attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY)) + attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.EXTERNAL)) + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR)) + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8) + } + outgoing.artifact(tasks.named("deobfJar")) +} + +val javaComponent = components["java"] as AdhocComponentWithVariants +javaComponent.addVariantsFromConfiguration(deobfElements.get()) { + mapToMavenScope("runtime") +} + +tasks.jar { + manifest { + attributes(mapOf( + "Specification-Title" to "terra", + "Specification-Vendor" to "Terra", + "Specification-Version" to "1.0", + "Implementation-Title" to "Terra", + "Implementation-Version" to project.version, + "Implementation-Vendor" to "terra", + "MixinConfigs" to "terra.mixins.json" + )) + } +} + +tasks.register("publishModrinthForge") { + dependsOn("reobfShadowJar") + group = "forge" + token = System.getenv("MODRINTH_SECRET") + projectId = "FIlZB9L0" + versionNumber = "${project.version}-forge" + uploadFile = tasks.named("reobfShadowJar").get().input.absoluteFile + releaseType = "alpha" + addGameVersion("1.16.5") + addLoader("forge") +} \ No newline at end of file diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/TerraForgePlugin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/TerraForgePlugin.java new file mode 100644 index 000000000..fe0d33cf1 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/TerraForgePlugin.java @@ -0,0 +1,510 @@ +package com.dfsek.terra.forge; + +import com.dfsek.tectonic.loading.TypeRegistry; +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.handle.ItemHandle; +import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.platform.world.Tree; +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.transform.NotNullValidator; +import com.dfsek.terra.api.transform.Transformer; +import com.dfsek.terra.api.util.JarUtil; +import com.dfsek.terra.api.util.logging.DebugLogger; +import com.dfsek.terra.api.util.mutable.MutableInteger; +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.config.templates.BiomeTemplate; +import com.dfsek.terra.forge.inventory.ForgeItemHandle; +import com.dfsek.terra.forge.world.ForgeAdapter; +import com.dfsek.terra.forge.world.ForgeBiome; +import com.dfsek.terra.forge.world.ForgeTree; +import com.dfsek.terra.forge.world.ForgeWorldHandle; +import com.dfsek.terra.forge.world.features.PopulatorFeature; +import com.dfsek.terra.forge.world.generator.ForgeChunkGenerator; +import com.dfsek.terra.forge.world.generator.ForgeChunkGeneratorWrapper; +import com.dfsek.terra.forge.world.generator.config.TerraLevelType; +import com.dfsek.terra.profiler.Profiler; +import com.dfsek.terra.profiler.ProfilerImpl; +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.ArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import net.minecraft.block.Blocks; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.button.Button; +import net.minecraft.command.CommandSource; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.BiomeAmbience; +import net.minecraft.world.biome.BiomeGenerationSettings; +import net.minecraft.world.gen.GenerationStage; +import net.minecraft.world.gen.feature.ConfiguredFeature; +import net.minecraft.world.gen.feature.Feature; +import net.minecraft.world.gen.feature.Features; +import net.minecraft.world.gen.feature.IFeatureConfig; +import net.minecraft.world.gen.feature.NoFeatureConfig; +import net.minecraft.world.gen.placement.DecoratedPlacement; +import net.minecraft.world.gen.placement.NoPlacementConfig; +import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder; +import net.minecraft.world.gen.surfacebuilders.SurfaceBuilderConfig; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.ForgeWorldTypeScreens; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.world.ForgeWorldType; +import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.minecraftforge.registries.ForgeRegistries; +import org.apache.commons.io.FileUtils; +import org.apache.logging.log4j.LogManager; +import org.objectweb.asm.Type; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.file.Paths; +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.Objects; +import java.util.function.Consumer; +import java.util.jar.JarFile; +import java.util.zip.ZipFile; + +import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal; +import static com.mojang.brigadier.builder.RequiredArgumentBuilder.argument; + +@Mod("terra") +@Mod.EventBusSubscriber(modid = "terra", bus = Mod.EventBusSubscriber.Bus.MOD) +public class TerraForgePlugin implements TerraPlugin { + public static final PopulatorFeature POPULATOR_FEATURE = (PopulatorFeature) new PopulatorFeature(NoFeatureConfig.CODEC).setRegistryName("terra", "terra"); + public static final ConfiguredFeature POPULATOR_CONFIGURED_FEATURE = POPULATOR_FEATURE.configured(IFeatureConfig.NONE).decorated(DecoratedPlacement.NOPE.configured(NoPlacementConfig.INSTANCE)); + + private static TerraForgePlugin INSTANCE; + private final Map worldMap = new HashMap<>(); + private final EventManager eventManager = new TerraEventManager(this); + private final GenericLoaders genericLoaders = new GenericLoaders(this); + private final Profiler profiler = new ProfilerImpl(); + + private final CommandManager manager = new TerraCommandManager(this); + + private final com.dfsek.terra.api.util.logging.Logger logger = new com.dfsek.terra.api.util.logging.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 ForgeItemHandle(); + private final WorldHandle worldHandle = new ForgeWorldHandle(); + private final ConfigRegistry registry = new ConfigRegistry(); + private final CheckedRegistry checkedRegistry = new CheckedRegistry<>(registry); + private final AddonRegistry addonRegistry = new AddonRegistry(new ForgeAddon(this), this); + private final LockedRegistry addonLockedRegistry = new LockedRegistry<>(addonRegistry); + private final PluginConfig config = new PluginConfig(); + private final Transformer biomeFixer = new Transformer.Builder() + .addTransform(id -> ForgeRegistries.BIOMES.getValue(ResourceLocation.tryParse(id)), new NotNullValidator<>()) + .addTransform(id -> ForgeRegistries.BIOMES.getValue(ResourceLocation.tryParse("minecraft:" + id.toLowerCase())), new NotNullValidator<>()).build(); + private File dataFolder; + + public TerraForgePlugin() { + if(INSTANCE != null) throw new IllegalStateException("Only one TerraPlugin instance may exist."); + INSTANCE = this; + MinecraftForge.EVENT_BUS.register(ClientEvents.class); + MinecraftForge.EVENT_BUS.register(getClass()); + MinecraftForge.EVENT_BUS.register(ForgeEvents.class); + } + + public static TerraForgePlugin getInstance() { + return INSTANCE; + } + + public static String createBiomeID(ConfigPack pack, String biomeID) { + return pack.getTemplate().getID().toLowerCase() + "/" + biomeID.toLowerCase(Locale.ROOT); + } + + private static RequiredArgumentBuilder assemble(RequiredArgumentBuilder in, CommandManager manager) { + return in.suggests((context, builder) -> { + List args = parseCommand(context.getInput()); + CommandSender sender = ForgeAdapter.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), ForgeAdapter.adapt(context.getSource()), args); + } catch(CommandException e) { + context.getSource().sendFailure(new StringTextComponent(e.getMessage())); + } + return 1; + }); + } + + private static 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; + } + + @SubscribeEvent + public static void register(RegistryEvent.Register event) { + INSTANCE.setup(); // Setup now because we need the biomes, and this event happens after blocks n stuff + INSTANCE.getConfigRegistry().forEach(pack -> pack.getRegistry(BiomeBuilder.class).forEach((id, biome) -> event.getRegistry().register(INSTANCE.createBiome(biome)))); // Register all Terra biomes. + } + + @SubscribeEvent + public static void registerLevels(RegistryEvent.Register event) { + INSTANCE.logger().info("Registering level types..."); + event.getRegistry().register(TerraLevelType.FORGE_WORLD_TYPE); + } + + @SubscribeEvent + public static void registerPop(RegistryEvent.Register> event) { + event.getRegistry().register(POPULATOR_FEATURE); + } + + public Biome createBiome(BiomeBuilder biome) { + BiomeTemplate template = biome.getTemplate(); + Map colors = template.getColors(); + + Biome vanilla = ((ForgeBiome) new ArrayList<>(biome.getVanillaBiomes().getContents()).get(0)).getHandle(); + + BiomeGenerationSettings.Builder generationSettings = new BiomeGenerationSettings.Builder(); + generationSettings.surfaceBuilder(SurfaceBuilder.DEFAULT.configured(new SurfaceBuilderConfig(Blocks.GRASS_BLOCK.defaultBlockState(), Blocks.DIRT.defaultBlockState(), Blocks.GRAVEL.defaultBlockState()))); // It needs a surfacebuilder, even though we dont use it. + generationSettings.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, POPULATOR_CONFIGURED_FEATURE); + + BiomeAmbience vanillaEffects = vanilla.getSpecialEffects(); + BiomeAmbience.Builder effects = new BiomeAmbience.Builder() + .waterColor(colors.getOrDefault("water", vanillaEffects.getWaterColor())) + .waterFogColor(colors.getOrDefault("water-fog", vanillaEffects.getWaterFogColor())) + .fogColor(colors.getOrDefault("fog", vanillaEffects.getFogColor())) + .skyColor(colors.getOrDefault("sky", vanillaEffects.getSkyColor())) + .grassColorModifier(vanillaEffects.getGrassColorModifier()); + + if(colors.containsKey("grass")) { + effects.grassColorOverride(colors.get("grass")); + } else { + vanillaEffects.getGrassColorOverride().ifPresent(effects::grassColorOverride); + } + vanillaEffects.getFoliageColorOverride().ifPresent(effects::foliageColorOverride); + if(colors.containsKey("foliage")) { + effects.foliageColorOverride(colors.get("foliage")); + } else { + vanillaEffects.getFoliageColorOverride().ifPresent(effects::foliageColorOverride); + } + + return new Biome.Builder() + .precipitation(vanilla.getPrecipitation()) + .biomeCategory(vanilla.getBiomeCategory()) + .depth(vanilla.getDepth()) + .scale(vanilla.getScale()) + .temperature(vanilla.getBaseTemperature()) + .downfall(vanilla.getDownfall()) + .specialEffects(effects.build()) + .mobSpawnSettings(vanilla.getMobSettings()) + .generationSettings(generationSettings.build()) + .build().setRegistryName("terra", createBiomeID(template.getPack(), template.getID())); + } + + public void setup() { + this.dataFolder = Paths.get("config", "Terra").toFile(); + saveDefaultConfig(); + 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."); + + + try { + CommandUtil.registerAll(manager); + } catch(MalformedCommandException e) { + e.printStackTrace(); // TODO do something here even though this should literally never happen + } + } + + @Override + public WorldHandle getWorldHandle() { + return worldHandle; + } + + @Override + public TerraWorld getWorld(World world) { + return worldMap.computeIfAbsent(world.getSeed(), w -> { + logger.info("Loading world " + w); + return new TerraWorld(world, ((ForgeChunkGeneratorWrapper) ((ForgeChunkGenerator) world.getGenerator()).getHandle()).getPack(), this); + }); + } + + @Override + public JarFile getModJar() throws URISyntaxException, IOException { + File modsDir = new File("./mods"); + + if(!modsDir.exists()) return JarUtil.getJarFile(); + + for(File file : Objects.requireNonNull(modsDir.listFiles((dir, name) -> name.endsWith(".jar")))) { + try(ZipFile zipFile = new ZipFile(file)) { + if(zipFile.getEntry(Type.getInternalName(TerraPlugin.class) + ".class") != null) { + return new JarFile(file); + } + } + } + return JarUtil.getJarFile(); + } + + public TerraWorld getWorld(long seed) { + TerraWorld world = worldMap.get(seed); + if(world == null) throw new IllegalArgumentException("No world exists with seed " + seed); + return world; + } + + @Override + public com.dfsek.terra.api.util.logging.Logger logger() { + return logger; + } + + @Override + public PluginConfig getTerraConfig() { + return config; + } + + @Override + public File getDataFolder() { + return dataFolder; + } + + @Override + public boolean isDebug() { + return true; + } + + @Override + public Language getLanguage() { + return LangUtil.getLanguage(); + } + + @Override + public CheckedRegistry getConfigRegistry() { + return checkedRegistry; + } + + @Override + 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 + public ItemHandle getItemHandle() { + return itemHandle; + } + + @Override + public void saveDefaultConfig() { + try(InputStream stream = getClass().getResourceAsStream("/config.yml")) { + File configFile = new File(getDataFolder(), "config.yml"); + if(!configFile.exists()) FileUtils.copyInputStreamToFile(stream, configFile); + } catch(IOException e) { + e.printStackTrace(); + } + } + + @Override + public String platformName() { + return "Forge"; + } + + @Override + public DebugLogger getDebugLogger() { + return debugLogger; + } + + @Override + public void register(TypeRegistry registry) { + genericLoaders.register(registry); + registry + .registerLoader(BlockData.class, (t, o, l) -> worldHandle.createBlockData((String) o)) + .registerLoader(com.dfsek.terra.api.platform.world.Biome.class, (t, o, l) -> new ForgeBiome(biomeFixer.translate((String) o))); + } + + @Override + public EventManager getEventManager() { + return eventManager; + } + + @Override + public Profiler getProfiler() { + return profiler; + } + + @Mod.EventBusSubscriber(modid = "terra", bus = Mod.EventBusSubscriber.Bus.FORGE) + public static final class ForgeEvents { + @SuppressWarnings({"unchecked", "rawtypes"}) + @SubscribeEvent + public static void registerCommands(RegisterCommandsEvent event) { + int max = INSTANCE.manager.getMaxArgumentDepth(); + RequiredArgumentBuilder arg = argument("arg" + (max - 1), StringArgumentType.word()); + for(int i = 0; i < max; i++) { + RequiredArgumentBuilder next = argument("arg" + (max - i - 1), StringArgumentType.word()); + + arg = next.then(assemble(arg, INSTANCE.manager)); + } + + event.getDispatcher().register(literal("terra").executes(context -> 1).then((ArgumentBuilder) assemble(arg, INSTANCE.manager))); + event.getDispatcher().register(literal("te").executes(context -> 1).then((ArgumentBuilder) assemble(arg, INSTANCE.manager))); + } + } + + @Addon("Terra-Forge") + @Author("Terra") + @Version("1.0.0") + private static final class ForgeAddon extends TerraAddon implements EventListener { + + private final TerraPlugin main; + + private ForgeAddon(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().getRegistry(Tree.class); + injectTree(treeRegistry, "BROWN_MUSHROOM", Features.HUGE_BROWN_MUSHROOM); + injectTree(treeRegistry, "RED_MUSHROOM", Features.HUGE_RED_MUSHROOM); + injectTree(treeRegistry, "JUNGLE", Features.MEGA_JUNGLE_TREE); + injectTree(treeRegistry, "JUNGLE_COCOA", Features.JUNGLE_TREE); + injectTree(treeRegistry, "LARGE_OAK", Features.FANCY_OAK); + injectTree(treeRegistry, "LARGE_SPRUCE", Features.PINE); + injectTree(treeRegistry, "SMALL_JUNGLE", Features.JUNGLE_TREE); + injectTree(treeRegistry, "SWAMP_OAK", Features.SWAMP_TREE); + injectTree(treeRegistry, "TALL_BIRCH", Features.BIRCH_TALL); + injectTree(treeRegistry, "ACACIA", Features.ACACIA); + injectTree(treeRegistry, "BIRCH", Features.BIRCH); + injectTree(treeRegistry, "DARK_OAK", Features.DARK_OAK); + injectTree(treeRegistry, "OAK", Features.OAK); + injectTree(treeRegistry, "CHORUS_PLANT", Features.CHORUS_PLANT); + injectTree(treeRegistry, "SPRUCE", Features.SPRUCE); + injectTree(treeRegistry, "JUNGLE_BUSH", Features.JUNGLE_BUSH); + injectTree(treeRegistry, "MEGA_SPRUCE", Features.MEGA_SPRUCE); + injectTree(treeRegistry, "CRIMSON_FUNGUS", Features.CRIMSON_FUNGI); + injectTree(treeRegistry, "WARPED_FUNGUS", Features.WARPED_FUNGI); + } + + + private void injectTree(CheckedRegistry registry, String id, ConfiguredFeature tree) { + try { + registry.add(id, new ForgeTree(tree, id, TerraForgePlugin.getInstance())); + } catch(DuplicateEntryException ignore) { + } + } + } + + @Mod.EventBusSubscriber(value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD) + public static final class ClientEvents { + @SubscribeEvent + public static void register(FMLClientSetupEvent event) { + INSTANCE.logger.info("Client setup..."); + + ForgeWorldType world = TerraLevelType.FORGE_WORLD_TYPE; + ForgeWorldTypeScreens.registerFactory(world, (returnTo, dimensionGeneratorSettings) -> new Screen(world.getDisplayName()) { + private final MutableInteger num = new MutableInteger(0); + private final List packs = new ArrayList<>(); + private final Button toggle = new Button(0, 25, 120, 20, new StringTextComponent(""), button -> { + num.increment(); + if(num.get() >= packs.size()) num.set(0); + button.setMessage(new StringTextComponent("Pack: " + packs.get(num.get()).getTemplate().getID())); + }); + + @Override + protected void init() { + packs.clear(); + INSTANCE.registry.forEach((Consumer) packs::add); + addButton(new Button(0, 0, 120, 20, new StringTextComponent("Close"), btn -> Minecraft.getInstance().setScreen(returnTo))); + toggle.setMessage(new StringTextComponent("Pack: " + packs.get(num.get()).getTemplate().getID())); + addButton(toggle); + } + }); + } + } + +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricEnchantment.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeEnchantment.java similarity index 57% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricEnchantment.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeEnchantment.java index 347f53315..8517c7118 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricEnchantment.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeEnchantment.java @@ -1,16 +1,17 @@ -package com.dfsek.terra.fabric.inventory; +package com.dfsek.terra.forge.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 com.dfsek.terra.forge.world.ForgeAdapter; import net.minecraft.util.registry.Registry; +import net.minecraftforge.registries.ForgeRegistries; import java.util.Objects; -public class FabricEnchantment implements Enchantment { +public class ForgeEnchantment implements Enchantment { private final net.minecraft.enchantment.Enchantment enchantment; - public FabricEnchantment(net.minecraft.enchantment.Enchantment enchantment) { + public ForgeEnchantment(net.minecraft.enchantment.Enchantment enchantment) { this.enchantment = enchantment; } @@ -21,17 +22,17 @@ public class FabricEnchantment implements Enchantment { @Override public boolean canEnchantItem(ItemStack itemStack) { - return enchantment.isAcceptableItem(FabricAdapter.adapt(itemStack)); + return enchantment.canEnchant(ForgeAdapter.adapt(itemStack)); } @Override public String getID() { - return Objects.requireNonNull(Registry.ENCHANTMENT.getId(enchantment)).toString(); + return Objects.requireNonNull(ForgeRegistries.ENCHANTMENTS.getKey(enchantment)).toString(); } @Override public boolean conflictsWith(Enchantment other) { - return !enchantment.canCombine(FabricAdapter.adapt(other)); + return !enchantment.isCompatibleWith(ForgeAdapter.adapt(other)); } @Override diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeInventory.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeInventory.java new file mode 100644 index 000000000..3109b1498 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeInventory.java @@ -0,0 +1,36 @@ +package com.dfsek.terra.forge.inventory; + +import com.dfsek.terra.api.platform.inventory.Inventory; +import com.dfsek.terra.api.platform.inventory.ItemStack; +import com.dfsek.terra.forge.world.ForgeAdapter; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.Items; + +public class ForgeInventory implements Inventory { + private final net.minecraft.inventory.IInventory delegate; + + public ForgeInventory(IInventory delegate) { + this.delegate = delegate; + } + + @Override + public net.minecraft.inventory.IInventory getHandle() { + return delegate; + } + + @Override + public int getSize() { + return delegate.getContainerSize(); + } + + @Override + public ItemStack getItem(int slot) { + net.minecraft.item.ItemStack itemStack = delegate.getItem(slot); + return itemStack.getItem() == Items.AIR ? null : ForgeAdapter.adapt(itemStack); + } + + @Override + public void setItem(int slot, ItemStack newStack) { + delegate.setItem(slot, ForgeAdapter.adapt(newStack)); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItem.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItem.java similarity index 67% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItem.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItem.java index 40c683119..2f332f768 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItem.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItem.java @@ -1,12 +1,12 @@ -package com.dfsek.terra.fabric.inventory; +package com.dfsek.terra.forge.inventory; import com.dfsek.terra.api.platform.inventory.Item; import com.dfsek.terra.api.platform.inventory.ItemStack; -public class FabricItem implements Item { +public class ForgeItem implements Item { private final net.minecraft.item.Item delegate; - public FabricItem(net.minecraft.item.Item delegate) { + public ForgeItem(net.minecraft.item.Item delegate) { this.delegate = delegate; } @@ -17,7 +17,7 @@ public class FabricItem implements Item { @Override public ItemStack newItemStack(int amount) { - return new FabricItemStack(new net.minecraft.item.ItemStack(delegate, amount)); + return new ForgeItemStack(new net.minecraft.item.ItemStack(delegate, amount)); } @Override diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItemHandle.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItemHandle.java new file mode 100644 index 000000000..6639b4a59 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItemHandle.java @@ -0,0 +1,37 @@ +package com.dfsek.terra.forge.inventory; + +import com.dfsek.terra.api.platform.handle.ItemHandle; +import com.dfsek.terra.api.platform.inventory.Item; +import com.dfsek.terra.api.platform.inventory.item.Enchantment; +import com.dfsek.terra.forge.world.ForgeAdapter; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.command.arguments.ItemArgument; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.registry.Registry; +import net.minecraftforge.registries.ForgeRegistries; + +import java.util.Set; +import java.util.stream.Collectors; + +public class ForgeItemHandle implements ItemHandle { + + @Override + public Item createItem(String data) { + try { + return ForgeAdapter.adapt(new ItemArgument().parse(new StringReader(data)).getItem()); + } catch(CommandSyntaxException e) { + throw new IllegalArgumentException("Invalid item data \"" + data + "\"", e); + } + } + + @Override + public Enchantment getEnchantment(String id) { + return ForgeAdapter.adapt(ForgeRegistries.ENCHANTMENTS.getValue(ResourceLocation.tryParse(id))); + } + + @Override + public Set getEnchantments() { + return ForgeRegistries.ENCHANTMENTS.getEntries().stream().map(entry -> ForgeAdapter.adapt(entry.getValue())).collect(Collectors.toSet()); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemStack.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItemStack.java similarity index 57% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemStack.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItemStack.java index 19d33b524..01e186bdb 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemStack.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItemStack.java @@ -1,15 +1,15 @@ -package com.dfsek.terra.fabric.inventory; +package com.dfsek.terra.forge.inventory; 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; +import com.dfsek.terra.forge.inventory.meta.ForgeDamageable; +import com.dfsek.terra.forge.inventory.meta.ForgeItemMeta; -public class FabricItemStack implements ItemStack { +public class ForgeItemStack implements ItemStack { private net.minecraft.item.ItemStack delegate; - public FabricItemStack(net.minecraft.item.ItemStack delegate) { + public ForgeItemStack(net.minecraft.item.ItemStack delegate) { this.delegate = delegate; } @@ -25,18 +25,18 @@ public class FabricItemStack implements ItemStack { @Override public Item getType() { - return new FabricItem(delegate.getItem()); + return new ForgeItem(delegate.getItem()); } @Override public ItemMeta getItemMeta() { - if(delegate.isDamageable()) return new FabricDamageable(delegate.copy()); - return new FabricItemMeta(delegate.copy()); + if(delegate.isDamageableItem()) return new ForgeDamageable(delegate.copy()); + return new ForgeItemMeta(delegate.copy()); } @Override public void setItemMeta(ItemMeta meta) { - this.delegate = ((FabricItemMeta) meta).getHandle(); + this.delegate = ((ForgeItemMeta) meta).getHandle(); } @Override diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/meta/FabricDamageable.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/meta/ForgeDamageable.java similarity index 50% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/meta/FabricDamageable.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/meta/ForgeDamageable.java index 4a4cc918e..6c0fab95d 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/meta/FabricDamageable.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/meta/ForgeDamageable.java @@ -1,25 +1,25 @@ -package com.dfsek.terra.fabric.inventory.meta; +package com.dfsek.terra.forge.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) { +public class ForgeDamageable extends ForgeItemMeta implements Damageable { + public ForgeDamageable(ItemStack delegate) { super(delegate); } @Override public int getDamage() { - return delegate.getDamage(); + return delegate.getDamageValue(); } @Override public void setDamage(int damage) { - delegate.setDamage(damage); + delegate.setDamageValue(damage); } @Override public boolean hasDamage() { - return delegate.isDamageable(); + return delegate.isDamaged(); } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/meta/FabricItemMeta.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/meta/ForgeItemMeta.java similarity index 55% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/meta/FabricItemMeta.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/meta/ForgeItemMeta.java index 2c4d9d079..7a28ade66 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/meta/FabricItemMeta.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/meta/ForgeItemMeta.java @@ -1,20 +1,21 @@ -package com.dfsek.terra.fabric.inventory.meta; +package com.dfsek.terra.forge.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 com.dfsek.terra.forge.world.ForgeAdapter; +import net.minecraft.command.arguments.NBTCompoundTagArgument; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.registry.Registry; import java.util.Collections; import java.util.HashMap; import java.util.Map; -public class FabricItemMeta implements ItemMeta { +public class ForgeItemMeta implements ItemMeta { protected final ItemStack delegate; - public FabricItemMeta(ItemStack delegate) { + public ForgeItemMeta(ItemStack delegate) { this.delegate = delegate; } @@ -25,18 +26,18 @@ public class FabricItemMeta implements ItemMeta { @Override public Map getEnchantments() { - if(!delegate.hasEnchantments()) return Collections.emptyMap(); + if(!delegate.isEnchanted()) 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")); + delegate.getEnchantmentTags().forEach(enchantment -> { + CompoundNBT eTag = (CompoundNBT) enchantment; + map.put(ForgeAdapter.adapt(Registry.ENCHANTMENT.byId(eTag.getInt("id"))), eTag.getInt("lvl")); }); return map; } @Override public void addEnchantment(Enchantment enchantment, int level) { - delegate.addEnchantment(FabricAdapter.adapt(enchantment), level); + delegate.enchant(ForgeAdapter.adapt(enchantment), level); } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeAdapter.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeAdapter.java new file mode 100644 index 000000000..1d34cdf03 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeAdapter.java @@ -0,0 +1,128 @@ +package com.dfsek.terra.forge.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.forge.inventory.ForgeEnchantment; +import com.dfsek.terra.forge.inventory.ForgeItem; +import com.dfsek.terra.forge.inventory.ForgeItemStack; +import com.dfsek.terra.forge.world.block.ForgeBlockData; +import com.dfsek.terra.forge.world.block.ForgeBlockType; +import com.dfsek.terra.forge.world.block.data.ForgeDirectional; +import com.dfsek.terra.forge.world.block.data.ForgeMultipleFacing; +import com.dfsek.terra.forge.world.block.data.ForgeOrientable; +import com.dfsek.terra.forge.world.block.data.ForgeRotatable; +import com.dfsek.terra.forge.world.block.data.ForgeSlab; +import com.dfsek.terra.forge.world.block.data.ForgeStairs; +import com.dfsek.terra.forge.world.block.data.ForgeWaterlogged; +import com.dfsek.terra.forge.world.entity.ForgeCommandSender; +import com.dfsek.terra.forge.world.entity.ForgeEntityType; +import com.dfsek.terra.forge.world.entity.ForgePlayer; +import com.dfsek.terra.forge.world.handles.world.ForgeWorldHandle; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.command.CommandSource; +import net.minecraft.command.ICommandSource; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorld; + +import java.util.Arrays; + +public final class ForgeAdapter { + 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 ForgeBlockData adapt(BlockState state) { + if(state.hasProperty(BlockStateProperties.STAIRS_SHAPE)) return new ForgeStairs(state); + + if(state.hasProperty(BlockStateProperties.SLAB_TYPE)) return new ForgeSlab(state); + + if(state.hasProperty(BlockStateProperties.AXIS)) return new ForgeOrientable(state, BlockStateProperties.AXIS); + if(state.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) return new ForgeOrientable(state, BlockStateProperties.HORIZONTAL_AXIS); + + if(state.hasProperty(BlockStateProperties.ROTATION_16)) return new ForgeRotatable(state); + + if(state.hasProperty(BlockStateProperties.FACING)) return new ForgeDirectional(state, BlockStateProperties.FACING); + if(state.hasProperty(BlockStateProperties.FACING_HOPPER)) return new ForgeDirectional(state, BlockStateProperties.FACING_HOPPER); + if(state.hasProperty(BlockStateProperties.HORIZONTAL_FACING)) return new ForgeDirectional(state, BlockStateProperties.HORIZONTAL_FACING); + + if(state.getProperties().containsAll(Arrays.asList(BlockStateProperties.NORTH, BlockStateProperties.SOUTH, BlockStateProperties.EAST, BlockStateProperties.WEST))) + return new ForgeMultipleFacing(state); + if(state.hasProperty(BlockStateProperties.WATERLOGGED)) return new ForgeWaterlogged(state); + return new ForgeBlockData(state); + } + + public static CommandSender adapt(CommandSource serverCommandSource) { + if(serverCommandSource.getEntity() instanceof PlayerEntity) return new ForgePlayer((PlayerEntity) serverCommandSource.getEntity()); + return new ForgeCommandSender(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 ForgeBlockType(block); + } + + public static EntityType adapt(net.minecraft.entity.EntityType entityType) { + return new ForgeEntityType(entityType); + } + + public static net.minecraft.entity.EntityType adapt(EntityType entityType) { + return ((ForgeEntityType) entityType).getHandle(); + } + + public static ItemStack adapt(com.dfsek.terra.api.platform.inventory.ItemStack itemStack) { + return ((ForgeItemStack) itemStack).getHandle(); + } + + public static com.dfsek.terra.api.platform.inventory.ItemStack adapt(ItemStack itemStack) { + return new ForgeItemStack(itemStack); + } + + public static com.dfsek.terra.api.platform.inventory.Item adapt(Item item) { + return new ForgeItem(item); + } + + public static Enchantment adapt(net.minecraft.enchantment.Enchantment enchantment) { + return new ForgeEnchantment(enchantment); + } + + public static net.minecraft.enchantment.Enchantment adapt(Enchantment enchantment) { + return ((ForgeEnchantment) enchantment).getHandle(); + } + + public IWorld adapt(ForgeWorldHandle worldHandle) { + return worldHandle.getWorld(); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricBiome.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeBiome.java similarity index 63% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricBiome.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeBiome.java index 99dab1c2c..cfddb6e88 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricBiome.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeBiome.java @@ -1,11 +1,11 @@ -package com.dfsek.terra.fabric.world; +package com.dfsek.terra.forge.world; import com.dfsek.terra.api.platform.world.Biome; -public class FabricBiome implements Biome { +public class ForgeBiome implements Biome { private final net.minecraft.world.biome.Biome delegate; - public FabricBiome(net.minecraft.world.biome.Biome delegate) { + public ForgeBiome(net.minecraft.world.biome.Biome delegate) { this.delegate = delegate; } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeTree.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeTree.java new file mode 100644 index 000000000..c94b85a29 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeTree.java @@ -0,0 +1,44 @@ +package com.dfsek.terra.forge.world; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.api.util.collections.MaterialSet; +import com.dfsek.terra.forge.world.generator.ForgeChunkGenerator; +import com.dfsek.terra.forge.world.handles.world.ForgeWorldAccess; +import com.dfsek.terra.profiler.ProfileFrame; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.ISeedReader; +import net.minecraft.world.gen.ChunkGenerator; +import net.minecraft.world.gen.feature.ConfiguredFeature; + +import java.util.Locale; +import java.util.Random; + +public class ForgeTree implements Tree { + private final ConfiguredFeature delegate; + private final String id; + private final TerraPlugin main; + + public ForgeTree(ConfiguredFeature delegate, String id, TerraPlugin main) { + this.delegate = delegate; + this.id = id; + this.main = main; + } + + @Override + public boolean plant(Location l, Random r) { + try(ProfileFrame ignore = main.getProfiler().profile("fabric_tree:" + id.toLowerCase(Locale.ROOT))) { + ForgeWorldAccess fabricWorldAccess = ((ForgeWorldAccess) l.getWorld()); + ChunkGenerator generatorWrapper = ((ForgeChunkGenerator) fabricWorldAccess.getGenerator()).getHandle(); + return delegate.place((ISeedReader) fabricWorldAccess.getHandle(), generatorWrapper, r, new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ())); + } + } + + @Override + public MaterialSet getSpawnable() { + return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:grass_block"), + main.getWorldHandle().createBlockData("minecraft:podzol"), + main.getWorldHandle().createBlockData("minecraft:mycelium")); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeWorldHandle.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeWorldHandle.java new file mode 100644 index 000000000..8e4cfafe6 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeWorldHandle.java @@ -0,0 +1,36 @@ +package com.dfsek.terra.forge.world; + +import com.dfsek.terra.api.platform.entity.EntityType; +import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.forge.world.block.ForgeBlockData; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.block.BlockState; +import net.minecraft.command.arguments.BlockStateParser; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.registry.Registry; +import net.minecraftforge.registries.ForgeRegistries; + +import java.util.Locale; + +public class ForgeWorldHandle implements WorldHandle { + + @Override + public ForgeBlockData createBlockData(String data) { + BlockStateParser parser = new BlockStateParser(new StringReader(data), true); + try { + BlockState state = parser.parse(true).getState(); + if(state == null) throw new IllegalArgumentException("Invalid data: " + data); + return ForgeAdapter.adapt(state); + } catch(CommandSyntaxException e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public EntityType getEntity(String id) { + ResourceLocation identifier = ResourceLocation.tryParse(id); + if(identifier == null) identifier = ResourceLocation.tryParse("minecraft:" + id.toLowerCase(Locale.ROOT)); + return ForgeAdapter.adapt(ForgeRegistries.ENTITIES.getValue(identifier)); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/TerraBiomeSource.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/TerraBiomeSource.java new file mode 100644 index 000000000..5f87a10b1 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/TerraBiomeSource.java @@ -0,0 +1,56 @@ +package com.dfsek.terra.forge.world; + +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.forge.TerraForgePlugin; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryLookupCodec; +import net.minecraft.world.biome.Biome; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; +import java.util.stream.Collectors; + +public class TerraBiomeSource extends net.minecraft.world.biome.provider.BiomeProvider { + public static final Codec PACK_CODEC = (RecordCodecBuilder.create(config -> config.group( + Codec.STRING.fieldOf("pack").forGetter(pack -> pack.getTemplate().getID()) + ).apply(config, config.stable(TerraForgePlugin.getInstance().getConfigRegistry()::get)))); + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + RegistryLookupCodec.create(Registry.BIOME_REGISTRY).forGetter(source -> source.biomeRegistry), + Codec.LONG.fieldOf("seed").stable().forGetter(source -> source.seed), + PACK_CODEC.fieldOf("pack").stable().forGetter(source -> source.pack)) + .apply(instance, instance.stable(TerraBiomeSource::new))); + + private final Registry biomeRegistry; + private final long seed; + private final BiomeProvider grid; + private final ConfigPack pack; + + public TerraBiomeSource(Registry biomes, long seed, ConfigPack pack) { + super(biomes.stream().collect(Collectors.toList())); + this.biomeRegistry = biomes; + this.seed = seed; + this.grid = pack.getBiomeProviderBuilder().build(seed); + this.pack = pack; + } + + @Override + protected @NotNull Codec codec() { + return CODEC; + } + + @Override + public net.minecraft.world.biome.provider.@NotNull BiomeProvider withSeed(long seed) { + return new TerraBiomeSource(this.biomeRegistry, seed, pack); + } + + @Override + public @NotNull Biome getNoiseBiome(int biomeX, int biomeY, int biomeZ) { + UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(biomeX << 2, biomeZ << 2); + return Objects.requireNonNull(biomeRegistry.get(new ResourceLocation("terra", TerraForgePlugin.createBiomeID(pack, biome.getID())))); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlock.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlock.java new file mode 100644 index 000000000..3d439d5d0 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlock.java @@ -0,0 +1,96 @@ +package com.dfsek.terra.forge.world.block; + +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.BlockType; +import com.dfsek.terra.api.platform.block.state.BlockState; +import com.dfsek.terra.forge.world.ForgeAdapter; +import com.dfsek.terra.forge.world.block.state.ForgeBlockState; +import com.dfsek.terra.forge.world.handles.world.ForgeWorldAccess; +import net.minecraft.block.FlowingFluidBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorld; + +public class ForgeBlock implements Block { + private final Handle delegate; + + public ForgeBlock(BlockPos position, IWorld worldAccess) { + this.delegate = new Handle(position, worldAccess); + } + + @Override + public void setBlockData(BlockData data, boolean physics) { + delegate.worldAccess.setBlock(delegate.position, ((ForgeBlockData) data).getHandle(), physics ? 3 : 1042); + if(physics && ((ForgeBlockData) data).getHandle().getBlock() instanceof FlowingFluidBlock) { + delegate.worldAccess.getLiquidTicks().scheduleTick(delegate.position, ((FlowingFluidBlock) ((ForgeBlockData) data).getHandle().getBlock()).getFluidState(((ForgeBlockData) data).getHandle()).getFluidState().getType(), 0); + } + } + + @Override + public BlockData getBlockData() { + return new ForgeBlockData(delegate.worldAccess.getBlockState(delegate.position)); + } + + @Override + public BlockState getState() { + return ForgeBlockState.newInstance(this); + } + + @Override + public Block getRelative(BlockFace face, int len) { + BlockPos newPos = delegate.position.offset(face.getModX() * len, face.getModY() * len, face.getModZ() * len); + return new ForgeBlock(newPos, delegate.worldAccess); + } + + @Override + public boolean isEmpty() { + return getBlockData().isAir(); + } + + @Override + public Location getLocation() { + return ForgeAdapter.adapt(delegate.position).toLocation(new ForgeWorldAccess(delegate.worldAccess)); + } + + @Override + public BlockType getType() { + return getBlockData().getBlockType(); + } + + @Override + public int getX() { + return delegate.position.getX(); + } + + @Override + public int getZ() { + return delegate.position.getZ(); + } + + @Override + public int getY() { + return delegate.position.getY(); + } + + @Override + public boolean isPassable() { + return isEmpty(); + } + + @Override + public Handle getHandle() { + return delegate; + } + + public static final class Handle { + private final BlockPos position; + private final IWorld worldAccess; + + public Handle(BlockPos position, IWorld worldAccess) { + this.position = position; + this.worldAccess = worldAccess; + } + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlockData.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlockData.java new file mode 100644 index 000000000..1a4ddb4b5 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlockData.java @@ -0,0 +1,84 @@ +package com.dfsek.terra.forge.world.block; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockType; +import com.dfsek.terra.forge.world.ForgeAdapter; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.state.Property; +import net.minecraftforge.registries.ForgeRegistries; + +import javax.annotation.Nullable; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class ForgeBlockData implements BlockData { + private static final Function, Comparable>, String> PROPERTY_MAPPER = new Function, Comparable>, String>() { + public String apply(@Nullable Map.Entry, Comparable> entry) { + if (entry == null) { + return ""; + } else { + Property property = entry.getKey(); + return property.getName() + "=" + this.getName(property, entry.getValue()); + } + } + + @SuppressWarnings("unchecked") + private > String getName(Property property, Comparable comparable) { + return property.getName((T)comparable); + } + }; + + protected BlockState delegate; + + public ForgeBlockData(BlockState delegate) { + this.delegate = delegate; + } + + @Override + public BlockType getBlockType() { + return ForgeAdapter.adapt(delegate.getBlock()); + } + + @Override + public boolean matches(BlockData other) { + return delegate.getBlock() == ((ForgeBlockData) other).delegate.getBlock(); + } + + @Override + public BlockData clone() { + try { + return (ForgeBlockData) super.clone(); + } catch(CloneNotSupportedException e) { + throw new Error(e); + } + } + + @Override + public String getAsString() { + StringBuilder data = new StringBuilder(Objects.requireNonNull(ForgeRegistries.BLOCKS.getKey(delegate.getBlock())).toString()); + if(!delegate.getProperties().isEmpty()) { + data.append('['); + data.append(delegate.getValues().entrySet().stream().map(PROPERTY_MAPPER).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 + public BlockState getHandle() { + return delegate; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlockType.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlockType.java similarity index 61% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlockType.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlockType.java index 26427bb2f..05c87167a 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlockType.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlockType.java @@ -1,15 +1,15 @@ -package com.dfsek.terra.fabric.world.block; +package com.dfsek.terra.forge.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 com.dfsek.terra.forge.world.ForgeAdapter; import net.minecraft.block.Block; import net.minecraft.block.Blocks; -public class FabricBlockType implements BlockType { +public class ForgeBlockType implements BlockType { private final Block delegate; - public FabricBlockType(Block delegate) { + public ForgeBlockType(Block delegate) { this.delegate = delegate; } @@ -20,12 +20,12 @@ public class FabricBlockType implements BlockType { @Override public BlockData getDefaultData() { - return FabricAdapter.adapt(delegate.getDefaultState()); + return ForgeAdapter.adapt(delegate.defaultBlockState()); } @Override public boolean isSolid() { - return delegate.getDefaultState().isOpaque(); + return delegate.defaultBlockState().canOcclude(); } @Override @@ -40,7 +40,7 @@ public class FabricBlockType implements BlockType { @Override public boolean equals(Object obj) { - if(!(obj instanceof FabricBlockType)) return false; - return ((FabricBlockType) obj).delegate == delegate; + if(!(obj instanceof ForgeBlockType)) return false; + return ((ForgeBlockType) obj).delegate == delegate; } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeAnaloguePowerable.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeAnaloguePowerable.java new file mode 100644 index 000000000..ff59ff1be --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeAnaloguePowerable.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.forge.world.block.data; + +import com.dfsek.terra.api.platform.block.data.AnaloguePowerable; +import com.dfsek.terra.forge.world.block.ForgeBlockData; +import net.minecraft.block.BlockState; + +/** + * None of this actually has implementation, TODO: implement this if we ever end up needing it. + */ +public class ForgeAnaloguePowerable extends ForgeBlockData implements AnaloguePowerable { + public ForgeAnaloguePowerable(BlockState delegate) { + super(delegate); + } + + @Override + public int getMaximumPower() { + return 0; + } + + @Override + public int getPower() { + return 0; + } + + @Override + public void setPower(int power) { + + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeDirectional.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeDirectional.java new file mode 100644 index 000000000..ec7c34242 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeDirectional.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.forge.world.block.data; + +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.Directional; +import com.dfsek.terra.forge.world.ForgeAdapter; +import com.dfsek.terra.forge.world.block.ForgeBlockData; +import net.minecraft.block.BlockState; +import net.minecraft.state.DirectionProperty; + +public class ForgeDirectional extends ForgeBlockData implements Directional { + private final DirectionProperty property; + + public ForgeDirectional(BlockState delegate, DirectionProperty property) { + super(delegate); + this.property = property; + } + + @Override + public BlockFace getFacing() { + switch(delegate.getValue(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.setValue(property, ForgeAdapter.adapt(facing)); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricEnumAdapter.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeEnumAdapter.java similarity index 82% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricEnumAdapter.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeEnumAdapter.java index 98f883059..d01c59f37 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricEnumAdapter.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeEnumAdapter.java @@ -1,17 +1,17 @@ -package com.dfsek.terra.fabric.world.block.data; +package com.dfsek.terra.forge.world.block.data; import com.dfsek.terra.api.platform.block.Axis; import com.dfsek.terra.api.platform.block.BlockFace; 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 net.minecraft.block.enums.BlockHalf; -import net.minecraft.block.enums.SlabType; -import net.minecraft.block.enums.StairShape; -import net.minecraft.util.math.Direction; +import net.minecraft.state.properties.Half; +import net.minecraft.state.properties.SlabType; +import net.minecraft.state.properties.StairsShape; +import net.minecraft.util.Direction; -public final class FabricEnumAdapter { - public static Stairs.Shape adapt(StairShape shape) { +public final class ForgeEnumAdapter { + public static Stairs.Shape adapt(StairsShape shape) { switch(shape) { case OUTER_RIGHT: return Stairs.Shape.OUTER_RIGHT; @@ -28,7 +28,7 @@ public final class FabricEnumAdapter { } } - public static Bisected.Half adapt(BlockHalf half) { + public static Bisected.Half adapt(Half half) { switch(half) { case BOTTOM: return Bisected.Half.BOTTOM; @@ -71,29 +71,29 @@ public final class FabricEnumAdapter { } } - public static StairShape adapt(Stairs.Shape shape) { + public static StairsShape adapt(Stairs.Shape shape) { switch(shape) { case STRAIGHT: - return StairShape.STRAIGHT; + return StairsShape.STRAIGHT; case INNER_LEFT: - return StairShape.INNER_LEFT; + return StairsShape.INNER_LEFT; case OUTER_LEFT: - return StairShape.OUTER_LEFT; + return StairsShape.OUTER_LEFT; case INNER_RIGHT: - return StairShape.INNER_RIGHT; + return StairsShape.INNER_RIGHT; case OUTER_RIGHT: - return StairShape.OUTER_RIGHT; + return StairsShape.OUTER_RIGHT; default: throw new IllegalStateException(); } } - public static BlockHalf adapt(Bisected.Half half) { + public static Half adapt(Bisected.Half half) { switch(half) { case TOP: - return BlockHalf.TOP; + return Half.TOP; case BOTTOM: - return BlockHalf.BOTTOM; + return Half.BOTTOM; default: throw new IllegalStateException(); } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeMultipleFacing.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeMultipleFacing.java new file mode 100644 index 000000000..4bfde3fcc --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeMultipleFacing.java @@ -0,0 +1,70 @@ +package com.dfsek.terra.forge.world.block.data; + +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.MultipleFacing; +import com.dfsek.terra.forge.world.block.ForgeBlockData; +import net.minecraft.block.BlockState; +import net.minecraft.state.properties.BlockStateProperties; + + +import java.util.HashSet; +import java.util.Set; + +public class ForgeMultipleFacing extends ForgeBlockData implements MultipleFacing { + public ForgeMultipleFacing(BlockState delegate) { + super(delegate); + } + + @Override + public Set getFaces() { + Set set = new HashSet<>(); + if(delegate.getValue(BlockStateProperties.NORTH)) set.add(BlockFace.NORTH); + if(delegate.getValue(BlockStateProperties.SOUTH)) set.add(BlockFace.SOUTH); + if(delegate.getValue(BlockStateProperties.EAST)) set.add(BlockFace.EAST); + if(delegate.getValue(BlockStateProperties.WEST)) set.add(BlockFace.WEST); + if(delegate.hasProperty(BlockStateProperties.UP) && delegate.getValue(BlockStateProperties.UP)) set.add(BlockFace.UP); + if(delegate.hasProperty(BlockStateProperties.DOWN) && delegate.getValue(BlockStateProperties.DOWN)) set.add(BlockFace.DOWN); + return set; + } + + @Override + public void setFace(BlockFace face, boolean facing) { + switch(face) { + case NORTH: + delegate = delegate.setValue(BlockStateProperties.NORTH, facing); + break; + case SOUTH: + delegate = delegate.setValue(BlockStateProperties.SOUTH, facing); + break; + case EAST: + delegate = delegate.setValue(BlockStateProperties.EAST, facing); + break; + case WEST: + delegate = delegate.setValue(BlockStateProperties.WEST, facing); + break; + case UP: + delegate = delegate.setValue(BlockStateProperties.UP, facing); + break; + case DOWN: + delegate = delegate.setValue(BlockStateProperties.DOWN, facing); + break; + } + } + + @Override + public Set getAllowedFaces() { + Set set = new HashSet<>(); + if(delegate.hasProperty(BlockStateProperties.NORTH)) set.add(BlockFace.NORTH); + if(delegate.hasProperty(BlockStateProperties.SOUTH)) set.add(BlockFace.SOUTH); + if(delegate.hasProperty(BlockStateProperties.EAST)) set.add(BlockFace.EAST); + if(delegate.hasProperty(BlockStateProperties.WEST)) set.add(BlockFace.WEST); + if(delegate.hasProperty(BlockStateProperties.UP)) set.add(BlockFace.UP); + if(delegate.hasProperty(BlockStateProperties.DOWN)) set.add(BlockFace.DOWN); + return set; + } + + @Override + public boolean hasFace(BlockFace f) { + return getFaces().contains(f); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeOrientable.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeOrientable.java new file mode 100644 index 000000000..39d3aa7f6 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeOrientable.java @@ -0,0 +1,37 @@ +package com.dfsek.terra.forge.world.block.data; + +import com.dfsek.terra.api.platform.block.Axis; +import com.dfsek.terra.api.platform.block.data.Orientable; +import com.dfsek.terra.forge.world.block.ForgeBlockData; +import net.minecraft.block.BlockState; +import net.minecraft.state.EnumProperty; +import net.minecraft.util.Direction; + + +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +public class ForgeOrientable extends ForgeBlockData implements Orientable { + private final EnumProperty property; + + public ForgeOrientable(BlockState delegate, EnumProperty property) { + super(delegate); + this.property = property; + } + + @Override + public Set getAxes() { + return Arrays.stream(Axis.values()).collect(Collectors.toSet()); + } + + @Override + public Axis getAxis() { + return ForgeEnumAdapter.adapt(getHandle().getValue(property)); + } + + @Override + public void setAxis(Axis axis) { + delegate = delegate.setValue(property, ForgeEnumAdapter.adapt(axis)); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeRotatable.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeRotatable.java new file mode 100644 index 000000000..70bc30111 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeRotatable.java @@ -0,0 +1,111 @@ +package com.dfsek.terra.forge.world.block.data; + +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.Rotatable; +import com.dfsek.terra.forge.world.block.ForgeBlockData; +import net.minecraft.block.BlockState; +import net.minecraft.state.properties.BlockStateProperties; + +public class ForgeRotatable extends ForgeBlockData implements Rotatable { + public ForgeRotatable(BlockState delegate) { + super(delegate); + } + + @Override + public BlockFace getRotation() { + int r = delegate.getValue(BlockStateProperties.ROTATION_16); + 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.setValue(BlockStateProperties.ROTATION_16, 0); + return; + case SOUTH_SOUTH_WEST: + delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 1); + return; + case SOUTH_WEST: + delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 2); + return; + case WEST_SOUTH_WEST: + delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 3); + return; + case WEST: + delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 4); + return; + case WEST_NORTH_WEST: + delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 5); + return; + case NORTH_WEST: + delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 6); + return; + case NORTH_NORTH_WEST: + delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 7); + return; + case NORTH: + delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 8); + return; + case NORTH_NORTH_EAST: + delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 9); + return; + case NORTH_EAST: + delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 10); + return; + case EAST_NORTH_EAST: + delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 11); + return; + case EAST: + delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 12); + return; + case EAST_SOUTH_EAST: + delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 13); + return; + case SOUTH_EAST: + delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 14); + return; + case SOUTH_SOUTH_EAST: + delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 15); + return; + } + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeSlab.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeSlab.java new file mode 100644 index 000000000..55c8daa2a --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeSlab.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.forge.world.block.data; + +import com.dfsek.terra.api.platform.block.data.Slab; +import net.minecraft.block.BlockState; +import net.minecraft.state.properties.BlockStateProperties; + +public class ForgeSlab extends ForgeWaterlogged implements Slab { + public ForgeSlab(BlockState delegate) { + super(delegate); + } + + @Override + public Type getType() { + return ForgeEnumAdapter.adapt(delegate.getValue(BlockStateProperties.SLAB_TYPE)); + } + + @Override + public void setType(Type type) { + delegate = delegate.setValue(BlockStateProperties.SLAB_TYPE, ForgeEnumAdapter.adapt(type)); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeStairs.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeStairs.java new file mode 100644 index 000000000..87fae372d --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeStairs.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.forge.world.block.data; + +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.Stairs; +import net.minecraft.block.BlockState; +import net.minecraft.state.properties.BlockStateProperties; + +public class ForgeStairs extends ForgeWaterlogged implements Stairs { + public ForgeStairs(BlockState delegate) { + super(delegate); + } + + @Override + public Shape getShape() { + return ForgeEnumAdapter.adapt(getHandle().getValue(BlockStateProperties.STAIRS_SHAPE)); + } + + @Override + public void setShape(Shape shape) { + super.delegate = getHandle().setValue(BlockStateProperties.STAIRS_SHAPE, ForgeEnumAdapter.adapt(shape)); + } + + @Override + public Half getHalf() { + return ForgeEnumAdapter.adapt(getHandle().getValue(BlockStateProperties.HALF)); + } + + @Override + public void setHalf(Half half) { + super.delegate = getHandle().setValue(BlockStateProperties.HALF, ForgeEnumAdapter.adapt(half)); + } + + @Override + public BlockFace getFacing() { + return ForgeEnumAdapter.adapt(getHandle().getValue(BlockStateProperties.HORIZONTAL_FACING)); + } + + @Override + public void setFacing(BlockFace facing) { + super.delegate = getHandle().setValue(BlockStateProperties.HORIZONTAL_FACING, ForgeEnumAdapter.adapt(facing)); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeWaterlogged.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeWaterlogged.java new file mode 100644 index 000000000..c67aa0be0 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeWaterlogged.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.forge.world.block.data; + +import com.dfsek.terra.api.platform.block.data.Waterlogged; +import com.dfsek.terra.forge.world.block.ForgeBlockData; +import net.minecraft.block.BlockState; +import net.minecraft.state.properties.BlockStateProperties; + +public class ForgeWaterlogged extends ForgeBlockData implements Waterlogged { + public ForgeWaterlogged(BlockState delegate) { + super(delegate); + } + + @Override + public boolean isWaterlogged() { + return delegate.getValue(BlockStateProperties.WATERLOGGED); + } + + @Override + public void setWaterlogged(boolean waterlogged) { + super.delegate = delegate.setValue(BlockStateProperties.WATERLOGGED, waterlogged); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeBlockState.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeBlockState.java new file mode 100644 index 000000000..1ad7a6098 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeBlockState.java @@ -0,0 +1,73 @@ +package com.dfsek.terra.forge.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.forge.world.ForgeAdapter; +import com.dfsek.terra.forge.world.block.ForgeBlock; +import com.dfsek.terra.forge.world.handles.world.ForgeWorldHandle; +import net.minecraft.tileentity.LockableLootTileEntity; +import net.minecraft.tileentity.MobSpawnerTileEntity; +import net.minecraft.tileentity.SignTileEntity; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.IWorld; + +public class ForgeBlockState implements BlockState { + protected final TileEntity blockEntity; + private final IWorld worldAccess; + + public ForgeBlockState(TileEntity blockEntity, IWorld worldAccess) { + this.blockEntity = blockEntity; + this.worldAccess = worldAccess; + } + + public static ForgeBlockState newInstance(Block block) { + IWorld worldAccess = ((ForgeWorldHandle) block.getLocation().getWorld()).getWorld(); + + TileEntity entity = worldAccess.getBlockEntity(ForgeAdapter.adapt(block.getLocation().toVector())); + if(entity instanceof SignTileEntity) { + return new ForgeSign((SignTileEntity) entity, worldAccess); + } else if(entity instanceof MobSpawnerTileEntity) { + return new ForgeMobSpawner((MobSpawnerTileEntity) entity, worldAccess); + } else if(entity instanceof LockableLootTileEntity) { + return new ForgeContainer((LockableLootTileEntity) entity, worldAccess); + } + return null; + } + + @Override + public TileEntity getHandle() { + return blockEntity; + } + + @Override + public Block getBlock() { + return new ForgeBlock(blockEntity.getBlockPos(), blockEntity.getLevel()); + } + + @Override + public int getX() { + return blockEntity.getBlockPos().getX(); + } + + @Override + public int getY() { + return blockEntity.getBlockPos().getY(); + } + + @Override + public int getZ() { + return blockEntity.getBlockPos().getZ(); + } + + @Override + public BlockData getBlockData() { + return ForgeAdapter.adapt(blockEntity.getBlockState()); + } + + @Override + public boolean update(boolean applyPhysics) { + worldAccess.getChunk(blockEntity.getBlockPos()).setBlockEntity(blockEntity.getBlockPos(), blockEntity); + return true; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeContainer.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeContainer.java new file mode 100644 index 000000000..c10c9ef03 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeContainer.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.forge.world.block.state; + +import com.dfsek.terra.api.platform.block.state.Container; +import com.dfsek.terra.api.platform.inventory.Inventory; +import com.dfsek.terra.forge.inventory.ForgeInventory; +import net.minecraft.tileentity.LockableLootTileEntity; +import net.minecraft.world.IWorld; + +public class ForgeContainer extends ForgeBlockState implements Container { + public ForgeContainer(LockableLootTileEntity blockEntity, IWorld worldAccess) { + super(blockEntity, worldAccess); + } + + @Override + public Inventory getInventory() { + return new ForgeInventory(((LockableLootTileEntity) blockEntity)); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricMobSpawner.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeMobSpawner.java similarity index 74% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricMobSpawner.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeMobSpawner.java index 8486e20c9..95ca3d941 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricMobSpawner.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeMobSpawner.java @@ -1,30 +1,31 @@ -package com.dfsek.terra.fabric.world.block.state; +package com.dfsek.terra.forge.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 com.dfsek.terra.forge.TerraForgePlugin; +import com.dfsek.terra.forge.world.ForgeAdapter; +import net.minecraft.tileentity.MobSpawnerTileEntity; import net.minecraft.util.registry.Registry; -import net.minecraft.world.WorldAccess; +import net.minecraft.world.IWorld; +import net.minecraftforge.registries.ForgeRegistries; 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 class ForgeMobSpawner extends ForgeBlockState implements MobSpawner { // TODO: finish implementation / refactor API because bukkit doesnt expose most of the stuff spawners can do - public FabricMobSpawner(MobSpawnerBlockEntity blockEntity, WorldAccess worldAccess) { + public ForgeMobSpawner(MobSpawnerTileEntity blockEntity, IWorld worldAccess) { super(blockEntity, worldAccess); } @Override public EntityType getSpawnedType() { - return FabricAdapter.adapt(Registry.ENTITY_TYPE.get(((MobSpawnerBlockEntity) blockEntity).getLogic().getEntityId())); + return ForgeAdapter.adapt(ForgeRegistries.ENTITIES.getValue(((MobSpawnerTileEntity) blockEntity).getSpawner().getSpawnerEntity().getType().getRegistryName())); } @Override public void setSpawnedType(@NotNull EntityType creatureType) { - ((MobSpawnerBlockEntity) blockEntity).getLogic().setEntityId(FabricAdapter.adapt(creatureType)); + ((MobSpawnerTileEntity) blockEntity).getSpawner().setEntityId(ForgeAdapter.adapt(creatureType)); } @Override @@ -102,7 +103,7 @@ public class FabricMobSpawner extends FabricBlockState implements MobSpawner { / SerialState.parse(state).forEach((k, v) -> { switch(k) { case "type": - setSpawnedType(TerraFabricPlugin.getInstance().getWorldHandle().getEntity(v)); + setSpawnedType(TerraForgePlugin.getInstance().getWorldHandle().getEntity(v)); return; case "delay": setDelay(Integer.parseInt(v)); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricSign.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeSign.java similarity index 52% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricSign.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeSign.java index 382e05387..899fe900e 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/state/FabricSign.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeSign.java @@ -1,37 +1,37 @@ -package com.dfsek.terra.fabric.world.block.state; +package com.dfsek.terra.forge.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 net.minecraft.tileentity.SignTileEntity; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.world.IWorld; import org.jetbrains.annotations.NotNull; -public class FabricSign extends FabricBlockState implements Sign { - public FabricSign(SignBlockEntity blockEntity, WorldAccess worldAccess) { +public class ForgeSign extends ForgeBlockState implements Sign { + public ForgeSign(SignTileEntity blockEntity, IWorld worldAccess) { super(blockEntity, worldAccess); } @Override public @NotNull String[] getLines() { - SignBlockEntity sign = (SignBlockEntity) blockEntity; + SignTileEntity sign = (SignTileEntity) blockEntity; return new String[] { - sign.getTextOnRow(0).asString(), - sign.getTextOnRow(1).asString(), - sign.getTextOnRow(2).asString(), - sign.getTextOnRow(3).asString() + sign.getMessage(0).getString(), + sign.getMessage(1).getString(), + sign.getMessage(2).getString(), + sign.getMessage(3).getString() }; } @Override public @NotNull String getLine(int index) throws IndexOutOfBoundsException { - return ((SignBlockEntity) blockEntity).getTextOnRow(index).asString(); + return ((SignTileEntity) blockEntity).getMessage(index).getString(); } @Override public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException { - ((SignBlockEntity) blockEntity).setTextOnRow(index, new LiteralText(line)); + ((SignTileEntity) blockEntity).setMessage(index, new StringTextComponent(line)); } @Override diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeCommandSender.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeCommandSender.java new file mode 100644 index 000000000..042efbae3 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeCommandSender.java @@ -0,0 +1,23 @@ +package com.dfsek.terra.forge.world.entity; + +import com.dfsek.terra.api.platform.CommandSender; +import net.minecraft.command.CommandSource; +import net.minecraft.util.text.StringTextComponent; + +public class ForgeCommandSender implements CommandSender { + private final CommandSource delegate; + + public ForgeCommandSender(CommandSource delegate) { + this.delegate = delegate; + } + + @Override + public void sendMessage(String message) { + delegate.sendSuccess(new StringTextComponent(message), true); + } + + @Override + public Object getHandle() { + return delegate; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeEntity.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeEntity.java new file mode 100644 index 000000000..df35af7fb --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeEntity.java @@ -0,0 +1,43 @@ +package com.dfsek.terra.forge.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.forge.world.ForgeAdapter; +import com.dfsek.terra.forge.world.handles.world.ForgeWorldAccess; +import com.dfsek.terra.forge.world.handles.world.ForgeWorldHandle; +import net.minecraft.world.server.ServerWorld; + +public class ForgeEntity implements Entity { + private final net.minecraft.entity.Entity delegate; + + public ForgeEntity(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 ForgeWorldAccess(delegate.level), ForgeAdapter.adapt(delegate.blockPosition())); + } + + @Override + public void setLocation(Location location) { + delegate.teleportTo(location.getX(), location.getY(), location.getZ()); + delegate.setLevel((ServerWorld) ((ForgeWorldHandle) location).getWorld()); + } + + @Override + public World getWorld() { + return new ForgeWorldAccess(delegate.level); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricEntityType.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeEntityType.java similarity index 59% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricEntityType.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeEntityType.java index 31d6aceb1..42ad0e91d 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricEntityType.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeEntityType.java @@ -1,11 +1,11 @@ -package com.dfsek.terra.fabric.world.entity; +package com.dfsek.terra.forge.world.entity; import com.dfsek.terra.api.platform.entity.EntityType; -public class FabricEntityType implements EntityType { +public class ForgeEntityType implements EntityType { private final net.minecraft.entity.EntityType type; - public FabricEntityType(net.minecraft.entity.EntityType type) { + public ForgeEntityType(net.minecraft.entity.EntityType type) { this.type = type; } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgePlayer.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgePlayer.java new file mode 100644 index 000000000..87ea1ebc1 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgePlayer.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.forge.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.forge.world.ForgeAdapter; +import com.dfsek.terra.forge.world.handles.world.ForgeWorldAccess; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.text.StringTextComponent; + +public class ForgePlayer implements Player { + private final PlayerEntity delegate; + + public ForgePlayer(PlayerEntity delegate) { + this.delegate = delegate; + } + + @Override + public void sendMessage(String message) { + delegate.displayClientMessage(new StringTextComponent(message), false); + } + + @Override + public Object getHandle() { + return delegate; + } + + @Override + public Location getLocation() { + return ForgeAdapter.adapt(delegate.blockPosition()).toLocation(new ForgeWorldAccess(delegate.level)); + } + + @Override + public World getWorld() { + return new ForgeWorldAccess(delegate.level); + } + + @Override + public void setLocation(Location location) { + delegate.teleportTo(location.getX(), location.getY(), location.getZ()); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/features/PopulatorFeature.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/features/PopulatorFeature.java new file mode 100644 index 000000000..6082b4d4e --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/features/PopulatorFeature.java @@ -0,0 +1,34 @@ +package com.dfsek.terra.forge.world.features; + +import com.dfsek.terra.forge.world.generator.ForgeChunkGenerator; +import com.dfsek.terra.forge.world.generator.ForgeChunkGeneratorWrapper; +import com.dfsek.terra.forge.world.handles.ForgeWorld; +import com.dfsek.terra.forge.world.handles.chunk.ForgeChunkWorldAccess; +import com.mojang.serialization.Codec; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.ISeedReader; +import net.minecraft.world.gen.ChunkGenerator; +import net.minecraft.world.gen.feature.Feature; +import net.minecraft.world.gen.feature.NoFeatureConfig; +import org.jetbrains.annotations.NotNull; + +import java.util.Random; + +/** + * Feature wrapper for Terra populator + */ +public class PopulatorFeature extends Feature { + public PopulatorFeature(Codec codec) { + super(codec); + } + + @Override + public boolean place(@NotNull ISeedReader world, @NotNull ChunkGenerator generator, @NotNull Random random, BlockPos pos, @NotNull NoFeatureConfig config) { + ForgeChunkGeneratorWrapper gen = (ForgeChunkGeneratorWrapper) generator; + ForgeChunkWorldAccess chunk = new ForgeChunkWorldAccess(world, pos.getX() >> 4, pos.getZ() >> 4); + ForgeWorld world1 = new ForgeWorld(world.getLevel(), new ForgeChunkGenerator(generator)); + gen.getHandle().getPopulators().forEach(populator -> populator.populate(world1, chunk)); + return true; + } + +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkData.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkData.java similarity index 51% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkData.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkData.java index 24ea33e9b..14415feed 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkData.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkData.java @@ -1,36 +1,37 @@ -package com.dfsek.terra.fabric.world.generator; +package com.dfsek.terra.forge.world.generator; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.world.generator.ChunkData; -import com.dfsek.terra.fabric.world.block.FabricBlockData; +import com.dfsek.terra.forge.world.block.ForgeBlockData; import net.minecraft.util.math.BlockPos; import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.IChunk; import org.jetbrains.annotations.NotNull; -public class FabricChunkData implements ChunkData { - private final Chunk handle; +public class ForgeChunkData implements ChunkData { + private final IChunk handle; - public FabricChunkData(Chunk handle) { + public ForgeChunkData(IChunk handle) { this.handle = handle; } @Override - public Chunk getHandle() { + public IChunk getHandle() { return handle; } @Override public int getMaxHeight() { - return handle.getHeight(); + return handle.getMaxBuildHeight(); } @Override public void setBlock(int x, int y, int z, @NotNull BlockData blockData) { - handle.setBlockState(new BlockPos(x, y, z), ((FabricBlockData) blockData).getHandle(), false); + handle.setBlockState(new BlockPos(x, y, z), ((ForgeBlockData) blockData).getHandle(), false); } @Override public @NotNull BlockData getBlockData(int x, int y, int z) { - return new FabricBlockData(handle.getBlockState(new BlockPos(x, y, z))); + return new ForgeBlockData(handle.getBlockState(new BlockPos(x, y, z))); } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkGenerator.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkGenerator.java new file mode 100644 index 000000000..dad4fe98b --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkGenerator.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.forge.world.generator; + +import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; + +public class ForgeChunkGenerator implements ChunkGenerator { + private final net.minecraft.world.gen.ChunkGenerator delegate; + + public ForgeChunkGenerator(net.minecraft.world.gen.ChunkGenerator delegate) { + this.delegate = delegate; + } + + @Override + public net.minecraft.world.gen.ChunkGenerator getHandle() { + return delegate; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkGeneratorWrapper.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkGeneratorWrapper.java new file mode 100644 index 000000000..e9a5ce20d --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkGeneratorWrapper.java @@ -0,0 +1,141 @@ +package com.dfsek.terra.forge.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.forge.TerraForgePlugin; +import com.dfsek.terra.forge.world.TerraBiomeSource; +import com.dfsek.terra.forge.world.handles.world.ForgeSeededWorldAccess; +import com.dfsek.terra.world.TerraWorld; +import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D; +import com.dfsek.terra.world.generation.math.samplers.Sampler; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.jafama.FastMath; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.registry.DynamicRegistries; +import net.minecraft.world.Blockreader; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.IWorld; +import net.minecraft.world.biome.BiomeManager; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.IChunk; +import net.minecraft.world.gen.ChunkGenerator; +import net.minecraft.world.gen.GenerationStage; +import net.minecraft.world.gen.Heightmap; +import net.minecraft.world.gen.WorldGenRegion; +import net.minecraft.world.gen.feature.structure.StructureManager; +import net.minecraft.world.gen.feature.template.TemplateManager; +import net.minecraft.world.gen.settings.DimensionStructuresSettings; +import net.minecraft.world.gen.settings.StructureSpreadSettings; +import org.jetbrains.annotations.NotNull; + +public class ForgeChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper { + private final long seed; + 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(TerraForgePlugin.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), + PACK_CODEC.fieldOf("pack").stable().forGetter(generator -> generator.pack)) + .apply(instance, instance.stable(ForgeChunkGeneratorWrapper::new))); + private final ConfigPack pack; + + public ConfigPack getPack() { + return pack; + } + + public ForgeChunkGeneratorWrapper(TerraBiomeSource biomeSource, long seed, ConfigPack configPack) { + super(biomeSource, new DimensionStructuresSettings(false)); + this.pack = configPack; + + this.delegate = new DefaultChunkGenerator3D(pack, TerraForgePlugin.getInstance()); + delegate.getMain().logger().info("Loading world with config pack " + pack.getTemplate().getID()); + this.biomeSource = biomeSource; + + this.seed = seed; + } + + @Override + protected @NotNull Codec codec() { + return CODEC; + } + + @Override + public @NotNull ChunkGenerator withSeed(long seed) { + return new ForgeChunkGeneratorWrapper((TerraBiomeSource) this.biomeSource.withSeed(seed), seed, pack); + } + + @Override + public void buildSurfaceAndBedrock(@NotNull WorldGenRegion p_225551_1_, @NotNull IChunk p_225551_2_) { + + } + + @Override + public boolean hasStronghold(@NotNull ChunkPos p_235952_1_) { + return false; + } + + @Override + public void createStructures(@NotNull DynamicRegistries p_242707_1_, @NotNull StructureManager p_242707_2_, @NotNull IChunk p_242707_3_, @NotNull TemplateManager p_242707_4_, long p_242707_5_) { + + } + + @Override + public void applyCarvers(long p_230350_1_, @NotNull BiomeManager p_230350_3_, @NotNull IChunk p_230350_4_, GenerationStage.@NotNull Carving p_230350_5_) { + // No caves + } + + @Override + public void fillFromNoise(@NotNull IWorld world, @NotNull StructureManager p_230352_2_, @NotNull IChunk chunk) { + ForgeSeededWorldAccess worldAccess = new ForgeSeededWorldAccess(world, seed, this); + delegate.generateChunkData(worldAccess, new FastRandom(), chunk.getPos().x, chunk.getPos().z, new ForgeChunkData(chunk)); + } + + @Override + public int getBaseHeight(int x, int z, Heightmap.@NotNull Type p_222529_3_) { + TerraWorld world = TerraForgePlugin.getInstance().getWorld(seed); + Sampler sampler = world.getConfig().getSamplerCache().getChunk(FastMath.floorDiv(x, 16), FastMath.floorDiv(z, 16)); + int cx = FastMath.floorMod(x, 16); + int cz = FastMath.floorMod(z, 16); + + int height = world.getWorld().getMaxHeight(); + + while (height >= 0 && sampler.sample(cx, height - 1, cz) < 0) { + height--; + } + + return height; + } + + @Override + public @NotNull IBlockReader getBaseColumn(int p_230348_1_, int p_230348_2_) { + int height = 64; // TODO: implementation + BlockState[] array = new BlockState[256]; + for(int y = 255; y >= 0; y--) { + if(y > height) { + if(y > getSeaLevel()) { + array[y] = Blocks.AIR.defaultBlockState(); + } else { + array[y] = Blocks.WATER.defaultBlockState(); + } + } else { + array[y] = Blocks.STONE.defaultBlockState(); + } + } + + return new Blockreader(array); + } + + + @Override + public TerraChunkGenerator getHandle() { + return delegate; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/config/TerraLevelType.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/config/TerraLevelType.java new file mode 100644 index 000000000..2d8503af7 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/config/TerraLevelType.java @@ -0,0 +1,24 @@ +package com.dfsek.terra.forge.world.generator.config; + +import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.forge.TerraForgePlugin; +import com.dfsek.terra.forge.world.TerraBiomeSource; +import com.dfsek.terra.forge.world.generator.ForgeChunkGeneratorWrapper; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.ChunkGenerator; +import net.minecraft.world.gen.DimensionSettings; +import net.minecraftforge.common.world.ForgeWorldType; + +public class TerraLevelType implements ForgeWorldType.IChunkGeneratorFactory { + public static final TerraLevelType TERRA_LEVEL_TYPE = new TerraLevelType(); + public static final ForgeWorldType FORGE_WORLD_TYPE = new ForgeWorldType(TERRA_LEVEL_TYPE).setRegistryName("terra", "world"); + @Override + public ChunkGenerator createChunkGenerator(Registry biomeRegistry, Registry dimensionSettingsRegistry, long seed, String generatorSettings) { + System.out.println(generatorSettings); + dimensionSettingsRegistry.forEach(System.out::println); + ConfigPack pack = TerraForgePlugin.getInstance().getConfigRegistry().get("DEFAULT"); + TerraForgePlugin.getInstance().logger().info("Creating generator for config pack " + pack.getTemplate().getID()); + return new ForgeChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, seed, pack), seed, pack); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/FabricWorld.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/ForgeWorld.java similarity index 54% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/FabricWorld.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/ForgeWorld.java index 097ddfcb1..a4bfa54e2 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/FabricWorld.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/ForgeWorld.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.fabric.world.handles; +package com.dfsek.terra.forge.world.handles; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.Block; @@ -7,24 +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 com.dfsek.terra.forge.world.ForgeAdapter; +import com.dfsek.terra.forge.world.block.ForgeBlock; +import com.dfsek.terra.forge.world.entity.ForgeEntity; +import com.dfsek.terra.forge.world.handles.chunk.ForgeChunk; +import com.dfsek.terra.forge.world.handles.world.ForgeWorldHandle; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.ServerWorldAccess; -import net.minecraft.world.WorldAccess; +import net.minecraft.world.IServerWorld; +import net.minecraft.world.server.ServerWorld; -import java.io.File; -import java.util.UUID; - -public class FabricWorld implements World, FabricWorldHandle { +public class ForgeWorld implements World, ForgeWorldHandle { private final Handle delegate; - public FabricWorld(ServerWorld world, ChunkGenerator generator) { + public ForgeWorld(ServerWorld world, ChunkGenerator generator) { this.delegate = new Handle(world, generator); } @@ -43,54 +39,34 @@ public class FabricWorld implements World, FabricWorldHandle { return delegate.generator; } - @Override - public String getName() { - return delegate.world.worldProperties.getLevelName(); - } - - @Override - public UUID getUID() { - return null; - } - - @Override - public boolean isChunkGenerated(int x, int z) { - return false; - } - @Override public Chunk getChunkAt(int x, int z) { - return new FabricChunk(delegate.world.getChunk(x, z)); - } - - @Override - public File getWorldFolder() { - return null; + return new ForgeChunk(delegate.world.getChunk(x, z)); } @Override public Block getBlockAt(int x, int y, int z) { BlockPos pos = new BlockPos(x, y, z); - return new FabricBlock(pos, delegate.world); + return new ForgeBlock(pos, delegate.world); } @Override public int hashCode() { - return ((ServerWorldAccess) delegate.world).toServerWorld().hashCode(); + return ((IServerWorld) delegate.world).getLevel().hashCode(); } @Override public boolean equals(Object obj) { - if(!(obj instanceof FabricWorld)) return false; - return ((ServerWorldAccess) ((FabricWorld) obj).delegate.world).toServerWorld().equals(((ServerWorldAccess) delegate.world).toServerWorld()); + if(!(obj instanceof ForgeWorld)) return false; + return ((IServerWorld) ((ForgeWorld) obj).delegate.world).getLevel().equals(((IServerWorld) delegate.world).getLevel()); } @Override public Entity spawnEntity(Location location, EntityType entityType) { - net.minecraft.entity.Entity entity = FabricAdapter.adapt(entityType).create(delegate.world); + net.minecraft.entity.Entity entity = ForgeAdapter.adapt(entityType).create(delegate.world); entity.setPos(location.getX(), location.getY(), location.getZ()); - delegate.world.spawnEntity(entity); - return new FabricEntity(entity); + delegate.world.addFreshEntity(entity); + return new ForgeEntity(entity); } @Override @@ -104,7 +80,7 @@ public class FabricWorld implements World, FabricWorldHandle { } @Override - public WorldAccess getWorld() { + public ServerWorld getWorld() { return delegate.getWorld(); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/chunk/FabricChunk.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/chunk/ForgeChunk.java similarity index 76% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/chunk/FabricChunk.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/chunk/ForgeChunk.java index f9b488fdf..da28514f9 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/chunk/FabricChunk.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/chunk/ForgeChunk.java @@ -1,17 +1,17 @@ -package com.dfsek.terra.fabric.world.handles.chunk; +package com.dfsek.terra.forge.world.handles.chunk; import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.fabric.world.block.FabricBlockData; +import com.dfsek.terra.forge.world.block.ForgeBlockData; import net.minecraft.util.math.BlockPos; import org.jetbrains.annotations.NotNull; -public class FabricChunk implements Chunk { +public class ForgeChunk implements Chunk { private final net.minecraft.world.chunk.Chunk chunk; - public FabricChunk(net.minecraft.world.chunk.Chunk chunk) { + public ForgeChunk(net.minecraft.world.chunk.Chunk chunk) { this.chunk = chunk; } @@ -42,7 +42,7 @@ public class FabricChunk implements Chunk { @Override public void setBlock(int x, int y, int z, @NotNull BlockData blockData) { - chunk.setBlockState(new BlockPos(x, y, z), ((FabricBlockData) blockData).getHandle(), false); + chunk.setBlockState(new BlockPos(x, y, z), ((ForgeBlockData) blockData).getHandle(), false); } @Override diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/chunk/FabricChunkWorldAccess.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/chunk/ForgeChunkWorldAccess.java similarity index 59% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/chunk/FabricChunkWorldAccess.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/chunk/ForgeChunkWorldAccess.java index 3eb0662e7..a405910c4 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/chunk/FabricChunkWorldAccess.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/chunk/ForgeChunkWorldAccess.java @@ -1,22 +1,22 @@ -package com.dfsek.terra.fabric.world.handles.chunk; +package com.dfsek.terra.forge.world.handles.chunk; import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.fabric.world.block.FabricBlock; -import com.dfsek.terra.fabric.world.block.FabricBlockData; -import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess; +import com.dfsek.terra.forge.world.block.ForgeBlock; +import com.dfsek.terra.forge.world.block.ForgeBlockData; +import com.dfsek.terra.forge.world.handles.world.ForgeWorldAccess; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.WorldAccess; +import net.minecraft.world.IWorld; import org.jetbrains.annotations.NotNull; -public class FabricChunkWorldAccess implements Chunk { - private final WorldAccess chunkRegion; +public class ForgeChunkWorldAccess implements Chunk { + private final IWorld chunkRegion; private final int x; private final int z; - public FabricChunkWorldAccess(WorldAccess chunkRegion, int x, int z) { + public ForgeChunkWorldAccess(IWorld chunkRegion, int x, int z) { this.chunkRegion = chunkRegion; this.x = x << 4; this.z = z << 4; @@ -34,23 +34,23 @@ public class FabricChunkWorldAccess implements Chunk { @Override public World getWorld() { - return new FabricWorldAccess(chunkRegion); + return new ForgeWorldAccess(chunkRegion); } @Override public Block getBlock(int x, int y, int z) { BlockPos pos = new BlockPos(x + this.x, y, z + this.z); - return new FabricBlock(pos, chunkRegion); + return new ForgeBlock(pos, chunkRegion); } @Override - public WorldAccess getHandle() { + public IWorld getHandle() { return chunkRegion; } @Override public void setBlock(int x, int y, int z, @NotNull BlockData blockData) { - chunkRegion.setBlockState(new BlockPos(x + this.x, y, z + this.z), ((FabricBlockData) blockData).getHandle(), 0); + chunkRegion.setBlock(new BlockPos(x + this.x, y, z + this.z), ((ForgeBlockData) blockData).getHandle(), 0); } @Override diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeSeededWorldAccess.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeSeededWorldAccess.java new file mode 100644 index 000000000..bbc5aa411 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeSeededWorldAccess.java @@ -0,0 +1,110 @@ +package com.dfsek.terra.forge.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.forge.world.ForgeAdapter; +import com.dfsek.terra.forge.world.block.ForgeBlock; +import com.dfsek.terra.forge.world.entity.ForgeEntity; +import com.dfsek.terra.forge.world.generator.ForgeChunkGenerator; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IServerWorld; +import net.minecraft.world.IWorld; +import net.minecraft.world.server.ServerWorld; + +public class ForgeSeededWorldAccess implements World, ForgeWorldHandle { + + private final Handle handle; + + public ForgeSeededWorldAccess(IWorld access, long seed, net.minecraft.world.gen.ChunkGenerator generator) { + this.handle = new Handle(access, seed, generator); + } + + @Override + public long getSeed() { + return handle.getSeed(); + } + + @Override + public int getMaxHeight() { + return handle.getWorldAccess().getMaxBuildHeight(); + } + + @Override + public ChunkGenerator getGenerator() { + return new ForgeChunkGenerator(handle.getGenerator()); + } + + @Override + public Chunk getChunkAt(int x, int z) { + return null; + } + + @Override + public Block getBlockAt(int x, int y, int z) { + BlockPos pos = new BlockPos(x, y, z); + return new ForgeBlock(pos, handle.worldAccess); + } + + @Override + public Entity spawnEntity(Location location, EntityType entityType) { + net.minecraft.entity.Entity entity = ForgeAdapter.adapt(entityType).create((ServerWorld) handle.worldAccess); + entity.setPos(location.getX(), location.getY(), location.getZ()); + handle.worldAccess.addFreshEntity(entity); + return new ForgeEntity(entity); + } + + @Override + public int getMinHeight() { + return 0; + } + + @Override + public int hashCode() { + return ((IServerWorld) handle.worldAccess).getLevel().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof ForgeSeededWorldAccess)) return false; + return ((IServerWorld) ((ForgeSeededWorldAccess) obj).handle.worldAccess).getLevel().equals(((IServerWorld) handle.worldAccess).getLevel()); + } + + @Override + public Handle getHandle() { + return handle; + } + + @Override + public IWorld getWorld() { + return handle.worldAccess; + } + + public static class Handle { + private final IWorld worldAccess; + private final long seed; + private final net.minecraft.world.gen.ChunkGenerator generator; + + public Handle(IWorld worldAccess, long seed, net.minecraft.world.gen.ChunkGenerator generator) { + this.worldAccess = worldAccess; + this.seed = seed; + this.generator = generator; + } + + public net.minecraft.world.gen.ChunkGenerator getGenerator() { + return generator; + } + + public long getSeed() { + return seed; + } + + public IWorld getWorldAccess() { + return worldAccess; + } + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeWorldAccess.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeWorldAccess.java new file mode 100644 index 000000000..8a061d49b --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeWorldAccess.java @@ -0,0 +1,85 @@ +package com.dfsek.terra.forge.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.forge.world.ForgeAdapter; +import com.dfsek.terra.forge.world.block.ForgeBlock; +import com.dfsek.terra.forge.world.entity.ForgeEntity; +import com.dfsek.terra.forge.world.generator.ForgeChunkGenerator; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.ISeedReader; +import net.minecraft.world.IServerWorld; +import net.minecraft.world.IWorld; + +public class ForgeWorldAccess implements World, ForgeWorldHandle { + private final IWorld delegate; + + public ForgeWorldAccess(IWorld delegate) { + this.delegate = delegate; + } + + @Override + public long getSeed() { + return ((ISeedReader) delegate).getSeed(); + } + + @Override + public int getMaxHeight() { + return delegate.getHeight(); + } + + @Override + public ChunkGenerator getGenerator() { + return new ForgeChunkGenerator(((IServerWorld) delegate).getLevel().getChunkSource().getGenerator()); + } + + @Override + public Chunk getChunkAt(int x, int z) { + return null; + } + + @Override + public Block getBlockAt(int x, int y, int z) { + BlockPos pos = new BlockPos(x, y, z); + return new ForgeBlock(pos, delegate); + } + + @Override + public Entity spawnEntity(Location location, EntityType entityType) { + net.minecraft.entity.Entity entity = ForgeAdapter.adapt(entityType).create(((IServerWorld) delegate).getLevel()); + entity.setPos(location.getX(), location.getY(), location.getZ()); + delegate.addFreshEntity(entity); + return new ForgeEntity(entity); + } + + @Override + public int getMinHeight() { + return 0; + } + + @Override + public IWorld getHandle() { + return delegate; + } + + @Override + public IWorld getWorld() { + return delegate; + } + + @Override + public int hashCode() { + return ((IServerWorld) delegate).getLevel().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof ForgeWorldAccess)) return false; + return ((IServerWorld) ((ForgeWorldAccess) obj).delegate).getLevel().equals(((IServerWorld) delegate).getLevel()); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeWorldHandle.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeWorldHandle.java new file mode 100644 index 000000000..a0790e276 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeWorldHandle.java @@ -0,0 +1,7 @@ +package com.dfsek.terra.forge.world.handles.world; + +import net.minecraft.world.IWorld; + +public interface ForgeWorldHandle { + IWorld getWorld(); +} diff --git a/platforms/forge/src/main/resources/META-INF/mods.toml b/platforms/forge/src/main/resources/META-INF/mods.toml new file mode 100644 index 000000000..15baa899e --- /dev/null +++ b/platforms/forge/src/main/resources/META-INF/mods.toml @@ -0,0 +1,17 @@ +modLoader="javafml" +loaderVersion="[36,)" +license="GNU General Public License, version 3.0" +issueTrackerURL="https://github.com/PolyhedralDev/Terra/issues/" +[[mods]] +modId="terra" +version="@VERSION@" +displayName="Terra" +displayURL="https://github.com/PolyhedralDev/Terra/" +authors="dfsek & Terra contributors" +description="Data-driven world generator" +[[dependencies.terra]] + modId="forge" + mandatory=true + versionRange="[36,)" + ordering="NONE" + side="BOTH" \ No newline at end of file diff --git a/platforms/forge/src/main/resources/pack.mcmeta b/platforms/forge/src/main/resources/pack.mcmeta new file mode 100644 index 000000000..e33bc0eb4 --- /dev/null +++ b/platforms/forge/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "Terra Resources", + "pack_format": 6 + } +} \ No newline at end of file diff --git a/platforms/forge/src/main/resources/terra.mixins.json b/platforms/forge/src/main/resources/terra.mixins.json new file mode 100644 index 000000000..c18783888 --- /dev/null +++ b/platforms/forge/src/main/resources/terra.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "package": "com.dfsek.terra.forge.mixin", + "compatibilityLevel": "JAVA_8", + "refmap": "terra-refmap.json", + "mixins": [ + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + }, + "minVersion": "0.8" +} \ No newline at end of file diff --git a/platforms/forge/src/test/resources/META-INF/mods.toml b/platforms/forge/src/test/resources/META-INF/mods.toml new file mode 100644 index 000000000..bb8120be8 --- /dev/null +++ b/platforms/forge/src/test/resources/META-INF/mods.toml @@ -0,0 +1,20 @@ +modLoader = "javafml" +loaderVersion = "[33,)" +license = "GNU General Public License, version 3.0" +issueTrackerURL = "https://github.com/PolyhedralDev/Terra/issues" +[[mods]] +modId = "terra" +version = "@VERSION@" +displayName = "Terra" +displayURL = "https://github.com/PolyhedralDev/Terra" +logoFile = "logo_text.png" +authors = "dfsek & Terra contributors" +description = ''' +Powerful data-driven world generator +''' +[[dependencies.terra]] +modId = "forge" +mandatory = true +versionRange = "[36.0.4,)" +ordering = "NONE" +side = "BOTH" \ No newline at end of file diff --git a/platforms/forge/src/test/resources/pack.mcmeta b/platforms/forge/src/test/resources/pack.mcmeta new file mode 100644 index 000000000..5ed246b25 --- /dev/null +++ b/platforms/forge/src/test/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "Terra resources", + "pack_format": 6 + } +} \ No newline at end of file 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 3aacfabb9..84b90b7d8 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 @@ -19,7 +19,6 @@ import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.UUID; public class DirectWorld implements World { private final long seed; @@ -46,21 +45,6 @@ public class DirectWorld implements World { return generator; } - @Override - public String getName() { - return null; - } - - @Override - public UUID getUID() { - return null; - } - - @Override - public boolean isChunkGenerated(int x, int z) { - return false; - } - @Override public Chunk getChunkAt(int x, int z) { MCAFile file = compute(x, z); @@ -72,11 +56,6 @@ public class DirectWorld implements World { return new DirectChunkData(chunk, this, x, z); } - @Override - public File getWorldFolder() { - return null; - } - @Override public Block getBlockAt(int x, int y, int z) { return new DirectBlock(this, new Vector3(x, y, z)); diff --git a/settings.gradle.kts b/settings.gradle.kts index 303d70045..8cd013d8d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -13,10 +13,11 @@ include("platforms:bukkit") include("platforms:fabric") include("platforms:region") include("platforms:sponge") +include("platforms:forge") pluginManagement { repositories { - maven(url = "http://maven.fabricmc.net") { + maven(url = "https://maven.fabricmc.net") { name = "Fabric" } gradlePluginPortal()