mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2025-07-03 16:35:50 +00:00
Merge pull request #145 from PolyhedralDev/dev/forge
Forge implementation
This commit is contained in:
commit
6da8924868
@ -1,6 +1,6 @@
|
|||||||
import com.dfsek.terra.getGitHash
|
import com.dfsek.terra.getGitHash
|
||||||
|
|
||||||
val versionObj = Version("5", "2", "0", true)
|
val versionObj = Version("5", "2", "1", true)
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
version = versionObj
|
version = versionObj
|
||||||
|
@ -21,7 +21,7 @@ fun Project.configureCompilation() {
|
|||||||
tasks.withType<JavaCompile> {
|
tasks.withType<JavaCompile> {
|
||||||
options.encoding = "UTF-8"
|
options.encoding = "UTF-8"
|
||||||
doFirst {
|
doFirst {
|
||||||
options.compilerArgs = mutableListOf("-Xlint:all")
|
options.compilerArgs.add("-Xlint:all")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ dependencies {
|
|||||||
"shadedApi"("commons-io:commons-io:2.4")
|
"shadedApi"("commons-io:commons-io:2.4")
|
||||||
|
|
||||||
"shadedApi"("com.dfsek:Paralithic:0.3.2")
|
"shadedApi"("com.dfsek:Paralithic:0.3.2")
|
||||||
"shadedApi"("com.dfsek:Tectonic:1.2.3")
|
"shadedApi"("com.dfsek:Tectonic:1.3.1")
|
||||||
"shadedApi"("net.jafama:jafama:2.3.2")
|
"shadedApi"("net.jafama:jafama:2.3.2")
|
||||||
"shadedApi"("org.yaml:snakeyaml:1.27")
|
"shadedApi"("org.yaml:snakeyaml:1.27")
|
||||||
"shadedApi"("org.ow2.asm:asm:9.0")
|
"shadedApi"("org.ow2.asm:asm:9.0")
|
||||||
|
@ -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.platform.world.World;
|
||||||
import com.dfsek.terra.api.registry.CheckedRegistry;
|
import com.dfsek.terra.api.registry.CheckedRegistry;
|
||||||
import com.dfsek.terra.api.registry.LockedRegistry;
|
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.DebugLogger;
|
||||||
import com.dfsek.terra.api.util.logging.Logger;
|
import com.dfsek.terra.api.util.logging.Logger;
|
||||||
import com.dfsek.terra.config.PluginConfig;
|
import com.dfsek.terra.config.PluginConfig;
|
||||||
@ -16,6 +17,9 @@ import com.dfsek.terra.profiler.Profiler;
|
|||||||
import com.dfsek.terra.world.TerraWorld;
|
import com.dfsek.terra.world.TerraWorld;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a Terra mod/plugin instance.
|
* Represents a Terra mod/plugin instance.
|
||||||
@ -67,4 +71,8 @@ public interface TerraPlugin extends LoaderRegistrar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Profiler getProfiler();
|
Profiler getProfiler();
|
||||||
|
|
||||||
|
default JarFile getModJar() throws URISyntaxException, IOException {
|
||||||
|
return JarUtil.getJarFile();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,18 +19,12 @@ public interface World extends Handle {
|
|||||||
|
|
||||||
String getName();
|
String getName();
|
||||||
|
|
||||||
UUID getUID();
|
|
||||||
|
|
||||||
boolean isChunkGenerated(int x, int z);
|
|
||||||
|
|
||||||
Chunk getChunkAt(int x, int z);
|
Chunk getChunkAt(int x, int z);
|
||||||
|
|
||||||
default Chunk getChunkAt(Location location) {
|
default Chunk getChunkAt(Location location) {
|
||||||
return getChunkAt(location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
return getChunkAt(location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
File getWorldFolder();
|
|
||||||
|
|
||||||
Block getBlockAt(int x, int y, int z);
|
Block getBlockAt(int x, int y, int z);
|
||||||
|
|
||||||
default Block getBlockAt(Location l) {
|
default Block getBlockAt(Location l) {
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
package com.dfsek.terra.api.util;
|
package com.dfsek.terra.api.util;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.TerraPlugin;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,12 +69,12 @@ public class PluginConfig implements ConfigTemplate {
|
|||||||
ConfigLoader loader = new ConfigLoader();
|
ConfigLoader loader = new ConfigLoader();
|
||||||
loader.load(this, file);
|
loader.load(this, file);
|
||||||
if(dumpDefaultConfig) { // Don't dump default config if already loaded.
|
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());
|
JarUtil.copyResourcesToDirectory(jar, "packs", new File(main.getDataFolder(), "packs").toString());
|
||||||
} catch(IOException | URISyntaxException e) {
|
} catch(IOException | URISyntaxException e) {
|
||||||
main.getDebugLogger().error("Failed to dump default config files!");
|
main.getDebugLogger().error("Failed to dump default config files!");
|
||||||
e.printStackTrace();
|
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) {
|
} catch(ConfigException | IOException e) {
|
||||||
|
@ -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.ChunkGenerator;
|
||||||
import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper;
|
import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class DummyWorld implements World {
|
public class DummyWorld implements World {
|
||||||
@Override
|
@Override
|
||||||
public Object getHandle() {
|
public Object getHandle() {
|
||||||
@ -38,26 +35,11 @@ public class DummyWorld implements World {
|
|||||||
return "DUMMY";
|
return "DUMMY";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public UUID getUID() {
|
|
||||||
return UUID.randomUUID();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isChunkGenerated(int x, int z) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Chunk getChunkAt(int x, int z) {
|
public Chunk getChunkAt(int x, int z) {
|
||||||
throw new UnsupportedOperationException("Cannot get chunk in DummyWorld");
|
throw new UnsupportedOperationException("Cannot get chunk in DummyWorld");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public File getWorldFolder() {
|
|
||||||
throw new UnsupportedOperationException("Cannot get folder of DummyWorld");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Block getBlockAt(int x, int y, int z) {
|
public Block getBlockAt(int x, int y, int z) {
|
||||||
throw new UnsupportedOperationException("Cannot get block in DummyWorld");
|
throw new UnsupportedOperationException("Cannot get block in DummyWorld");
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.dfsek.terra.config.fileloaders;
|
package com.dfsek.terra.config.fileloaders;
|
||||||
|
|
||||||
|
import com.dfsek.tectonic.config.Configuration;
|
||||||
import com.dfsek.tectonic.exception.ConfigException;
|
import com.dfsek.tectonic.exception.ConfigException;
|
||||||
import com.dfsek.terra.api.util.GlueList;
|
import com.dfsek.terra.api.util.GlueList;
|
||||||
|
|
||||||
@ -18,8 +19,12 @@ public abstract class Loader {
|
|||||||
*
|
*
|
||||||
* @param consumer Something to do with the streams.
|
* @param consumer Something to do with the streams.
|
||||||
*/
|
*/
|
||||||
public Loader then(ExceptionalConsumer<List<InputStream>> consumer) throws ConfigException {
|
public Loader then(ExceptionalConsumer<List<Configuration>> consumer) throws ConfigException {
|
||||||
consumer.accept(new GlueList<>(streams.values()));
|
List<Configuration> list = new GlueList<>();
|
||||||
|
streams.forEach((id, stream) -> {
|
||||||
|
list.add(new Configuration(stream, id));
|
||||||
|
});
|
||||||
|
consumer.accept(list);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ public final class LangUtil {
|
|||||||
public static void load(String langID, TerraPlugin main) {
|
public static void load(String langID, TerraPlugin main) {
|
||||||
Logger logger = main.logger();
|
Logger logger = main.logger();
|
||||||
File file = new File(main.getDataFolder(), "lang");
|
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());
|
copyResourcesToDirectory(jar, "lang", file.toString());
|
||||||
} catch(IOException | URISyntaxException e) {
|
} catch(IOException | URISyntaxException e) {
|
||||||
main.getDebugLogger().error("Failed to dump language files!");
|
main.getDebugLogger().error("Failed to dump language files!");
|
||||||
|
@ -237,13 +237,13 @@ public class ConfigPack implements LoaderRegistrar {
|
|||||||
}).close();
|
}).close();
|
||||||
|
|
||||||
loader
|
loader
|
||||||
.open("carving", ".yml").then(streams -> buildAll(new CarverFactory(this), carverRegistry, abstractConfigLoader.load(streams, CarverTemplate::new), main)).close()
|
.open("carving", ".yml").then(configs -> buildAll(new CarverFactory(this), carverRegistry, abstractConfigLoader.loadConfigs(configs, CarverTemplate::new), main)).close()
|
||||||
.open("palettes", ".yml").then(streams -> buildAll(new PaletteFactory(), paletteRegistry, abstractConfigLoader.load(streams, PaletteTemplate::new), main)).close()
|
.open("palettes", ".yml").then(configs -> buildAll(new PaletteFactory(), paletteRegistry, abstractConfigLoader.loadConfigs(configs, PaletteTemplate::new), main)).close()
|
||||||
.open("ores", ".yml").then(streams -> buildAll(new OreFactory(), oreRegistry, abstractConfigLoader.load(streams, OreTemplate::new), main)).close()
|
.open("ores", ".yml").then(configs -> buildAll(new OreFactory(), oreRegistry, abstractConfigLoader.loadConfigs(configs, OreTemplate::new), main)).close()
|
||||||
.open("structures/trees", ".yml").then(streams -> buildAll(new TreeFactory(), treeRegistry, abstractConfigLoader.load(streams, TreeTemplate::new), main)).close()
|
.open("structures/trees", ".yml").then(configs -> buildAll(new TreeFactory(), treeRegistry, abstractConfigLoader.loadConfigs(configs, TreeTemplate::new), main)).close()
|
||||||
.open("structures/structures", ".yml").then(streams -> buildAll(new StructureFactory(), structureRegistry, abstractConfigLoader.load(streams, StructureTemplate::new), main)).close()
|
.open("structures/structures", ".yml").then(configs -> buildAll(new StructureFactory(), structureRegistry, abstractConfigLoader.loadConfigs(configs, StructureTemplate::new), main)).close()
|
||||||
.open("flora", ".yml").then(streams -> buildAll(new FloraFactory(), floraRegistry, abstractConfigLoader.load(streams, FloraTemplate::new), main)).close()
|
.open("flora", ".yml").then(configs -> buildAll(new FloraFactory(), floraRegistry, abstractConfigLoader.loadConfigs(configs, FloraTemplate::new), main)).close()
|
||||||
.open("biomes", ".yml").then(streams -> buildAll(new BiomeFactory(this), biomeRegistry, abstractConfigLoader.load(streams, () -> new BiomeTemplate(this, main)), main)).close();
|
.open("biomes", ".yml").then(configs -> buildAll(new BiomeFactory(this), biomeRegistry, abstractConfigLoader.loadConfigs(configs, () -> new BiomeTemplate(this, main)), main)).close();
|
||||||
|
|
||||||
main.getEventManager().callEvent(new ConfigPackPostLoadEvent(this));
|
main.getEventManager().callEvent(new ConfigPackPostLoadEvent(this));
|
||||||
main.logger().info("Loaded config pack \"" + template.getID() + "\" v" + template.getVersion() + " by " + template.getAuthor() + " in " + (System.nanoTime() - start) / 1000000D + "ms.");
|
main.logger().info("Loaded config pack \"" + template.getID() + "\" v" + template.getVersion() + " by " + template.getAuthor() + " in " + (System.nanoTime() - start) / 1000000D + "ms.");
|
||||||
|
@ -65,7 +65,9 @@ public class OpenRegistry<T> implements Registry<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T get(String identifier) {
|
public T get(String identifier) {
|
||||||
return objects.get(identifier).getValue();
|
Entry<T> entry = objects.get(identifier);
|
||||||
|
if(entry == null) return null;
|
||||||
|
return entry.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -68,10 +68,4 @@ public class FloraRegistry extends OpenRegistry<Flora> {
|
|||||||
private BlockData data(String s) {
|
private BlockData data(String s) {
|
||||||
return main.getWorldHandle().createBlockData(s);
|
return main.getWorldHandle().createBlockData(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Flora get(String identifier) {
|
|
||||||
return super.get(identifier);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -103,9 +103,10 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
|
|||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({"try"})
|
@SuppressWarnings({"try"})
|
||||||
public ChunkData generateChunkData(@NotNull World world, Random random, int chunkX, int chunkZ, ChunkData chunk) {
|
public ChunkData generateChunkData(@NotNull World world, Random random, int chunkX, int chunkZ, ChunkData chunk) {
|
||||||
TerraWorld tw = main.getWorld(world);
|
|
||||||
BiomeProvider grid = tw.getBiomeProvider();
|
|
||||||
try(ProfileFrame ignore = main.getProfiler().profile("chunk_base_3d")) {
|
try(ProfileFrame ignore = main.getProfiler().profile("chunk_base_3d")) {
|
||||||
|
TerraWorld tw = main.getWorld(world);
|
||||||
|
BiomeProvider grid = tw.getBiomeProvider();
|
||||||
|
|
||||||
if(!tw.isSafe()) return chunk;
|
if(!tw.isSafe()) return chunk;
|
||||||
int xOrig = (chunkX << 4);
|
int xOrig = (chunkX << 4);
|
||||||
int zOrig = (chunkZ << 4);
|
int zOrig = (chunkZ << 4);
|
||||||
@ -119,7 +120,7 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
|
|||||||
int cx = xOrig + x;
|
int cx = xOrig + x;
|
||||||
int cz = zOrig + z;
|
int cz = zOrig + z;
|
||||||
|
|
||||||
TerraBiome b = grid.getBiome(xOrig + x, zOrig + z);
|
TerraBiome b = grid.getBiome(cx, cz);
|
||||||
BiomeTemplate c = ((UserDefinedBiome) b).getConfig();
|
BiomeTemplate c = ((UserDefinedBiome) b).getConfig();
|
||||||
|
|
||||||
int sea = c.getSeaLevel();
|
int sea = c.getSeaLevel();
|
||||||
|
@ -159,7 +159,7 @@ public class DistributionTest {
|
|||||||
new GenericLoaders(MAIN).register(loader);
|
new GenericLoaders(MAIN).register(loader);
|
||||||
|
|
||||||
BiomeRegistry biomeRegistry = new BiomeRegistry();
|
BiomeRegistry biomeRegistry = new BiomeRegistry();
|
||||||
folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.load(inputStreams, TestBiome::new), MAIN));
|
folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.loadConfigs(inputStreams, TestBiome::new), MAIN));
|
||||||
|
|
||||||
BiomeProviderTemplate template = new BiomeProviderTemplate();
|
BiomeProviderTemplate template = new BiomeProviderTemplate();
|
||||||
ConfigLoader pipeLoader = new ConfigLoader()
|
ConfigLoader pipeLoader = new ConfigLoader()
|
||||||
|
@ -46,7 +46,7 @@ public class ImageTest {
|
|||||||
|
|
||||||
OpenRegistry<TerraBiome> biomeRegistry = new OpenRegistry<TerraBiome>() {
|
OpenRegistry<TerraBiome> biomeRegistry = new OpenRegistry<TerraBiome>() {
|
||||||
};
|
};
|
||||||
folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.load(inputStreams, TestBiome::new), null));
|
folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.loadConfigs(inputStreams, TestBiome::new), null));
|
||||||
|
|
||||||
return new ImageBiomeProvider(biomeRegistry.entries(), ImageIO.read(ImageTest.class.getResourceAsStream("/map.jpg")), 1, ImageBiomeProvider.Align.CENTER);
|
return new ImageBiomeProvider(biomeRegistry.entries(), ImageIO.read(ImageTest.class.getResourceAsStream("/map.jpg")), 1, ImageBiomeProvider.Align.CENTER);
|
||||||
}
|
}
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
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
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
org.gradle.jvmargs=-Xmx4096m
|
org.gradle.jvmargs=-Xmx4096m
|
@ -2,6 +2,7 @@ package com.dfsek.terra.bukkit.population;
|
|||||||
|
|
||||||
|
|
||||||
import com.dfsek.terra.api.platform.world.Chunk;
|
import com.dfsek.terra.api.platform.world.Chunk;
|
||||||
|
import com.dfsek.terra.bukkit.world.BukkitWorld;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -21,7 +22,7 @@ public class ChunkCoordinate implements Serializable {
|
|||||||
public ChunkCoordinate(Chunk c) {
|
public ChunkCoordinate(Chunk c) {
|
||||||
this.x = c.getX();
|
this.x = c.getX();
|
||||||
this.z = c.getZ();
|
this.z = c.getZ();
|
||||||
this.worldID = c.getWorld().getUID();
|
this.worldID = ((BukkitWorld) c.getWorld()).getUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID getWorldID() {
|
public UUID getWorldID() {
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,6 +8,7 @@ import com.dfsek.terra.api.world.generation.Chunkified;
|
|||||||
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
|
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
|
||||||
import com.dfsek.terra.bukkit.TerraBukkitPlugin;
|
import com.dfsek.terra.bukkit.TerraBukkitPlugin;
|
||||||
import com.dfsek.terra.bukkit.world.BukkitAdapter;
|
import com.dfsek.terra.bukkit.world.BukkitAdapter;
|
||||||
|
import com.dfsek.terra.bukkit.world.BukkitWorld;
|
||||||
import com.dfsek.terra.profiler.ProfileFrame;
|
import com.dfsek.terra.profiler.ProfileFrame;
|
||||||
import org.bukkit.generator.BlockPopulator;
|
import org.bukkit.generator.BlockPopulator;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -32,21 +33,28 @@ public class PopulationManager extends BlockPopulator {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public synchronized void saveBlocks(World w) throws IOException {
|
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();
|
f.createNewFile();
|
||||||
SerializationUtil.toFile((HashSet<ChunkCoordinate>) needsPop.clone(), f);
|
SerializationUtil.toFile((HashSet<ChunkCoordinate>) needsPop.clone(), f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public synchronized void loadBlocks(World w) throws IOException, ClassNotFoundException {
|
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<ChunkCoordinate>) SerializationUtil.fromFile(f));
|
needsPop.addAll((HashSet<ChunkCoordinate>) 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.
|
// Synchronize to prevent chunks from being queued for population multiple times.
|
||||||
public synchronized void checkNeighbors(int x, int z, World w) {
|
public synchronized void checkNeighbors(int x, int z, World world) {
|
||||||
ChunkCoordinate c = new ChunkCoordinate(x, z, w.getUID());
|
BukkitWorld w = (BukkitWorld) world;
|
||||||
|
ChunkCoordinate c = new ChunkCoordinate(x, z, (w).getUID());
|
||||||
if(w.isChunkGenerated(x + 1, z)
|
if(w.isChunkGenerated(x + 1, z)
|
||||||
&& w.isChunkGenerated(x - 1, z)
|
&& w.isChunkGenerated(x - 1, z)
|
||||||
&& w.isChunkGenerated(x, z + 1)
|
&& w.isChunkGenerated(x, z + 1)
|
||||||
|
@ -42,12 +42,10 @@ public class BukkitWorld implements World {
|
|||||||
return delegate.getName();
|
return delegate.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public UUID getUID() {
|
public UUID getUID() {
|
||||||
return delegate.getUID();
|
return delegate.getUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isChunkGenerated(int x, int z) {
|
public boolean isChunkGenerated(int x, int z) {
|
||||||
return delegate.isChunkGenerated(x, z);
|
return delegate.isChunkGenerated(x, z);
|
||||||
}
|
}
|
||||||
@ -57,7 +55,6 @@ public class BukkitWorld implements World {
|
|||||||
return BukkitAdapter.adapt(delegate.getChunkAt(x, z));
|
return BukkitAdapter.adapt(delegate.getChunkAt(x, z));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public File getWorldFolder() {
|
public File getWorldFolder() {
|
||||||
return delegate.getWorldFolder();
|
return delegate.getWorldFolder();
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ dependencies {
|
|||||||
|
|
||||||
configure<LoomGradleExtension> {
|
configure<LoomGradleExtension> {
|
||||||
accessWidener("src/main/resources/terra.accesswidener")
|
accessWidener("src/main/resources/terra.accesswidener")
|
||||||
|
refmapName = "terra.refmap.json"
|
||||||
}
|
}
|
||||||
|
|
||||||
val remapped = tasks.register<RemapJarTask>("remapShadedJar") {
|
val remapped = tasks.register<RemapJarTask>("remapShadedJar") {
|
||||||
@ -46,7 +47,7 @@ val remapped = tasks.register<RemapJarTask>("remapShadedJar") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tasks.register<TaskModrinthUpload>("publishModrinth") {
|
tasks.register<TaskModrinthUpload>("publishModrinthFabric") {
|
||||||
dependsOn("remapShadedJar")
|
dependsOn("remapShadedJar")
|
||||||
group = "fabric"
|
group = "fabric"
|
||||||
token = System.getenv("MODRINTH_SECRET")
|
token = System.getenv("MODRINTH_SECRET")
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
package com.dfsek.terra.fabric.command;
|
|
||||||
|
|
||||||
public class FabricCommandAdapter {
|
|
||||||
public static void register() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<List<String>> {
|
|
||||||
@Override
|
|
||||||
public List<String> parse(StringReader reader) {
|
|
||||||
final String text = reader.getRemaining();
|
|
||||||
reader.setCursor(reader.getTotalLength());
|
|
||||||
return new ArrayList<>(Arrays.asList(text.split(" ")));
|
|
||||||
}
|
|
||||||
}
|
|
@ -13,16 +13,17 @@ import net.minecraft.world.dimension.DimensionOptions;
|
|||||||
import net.minecraft.world.dimension.DimensionType;
|
import net.minecraft.world.dimension.DimensionType;
|
||||||
import net.minecraft.world.gen.GeneratorOptions;
|
import net.minecraft.world.gen.GeneratorOptions;
|
||||||
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
|
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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
// Mixins commented out until loom fixes multi-project builds.
|
@Mixin(GeneratorOptions.class)
|
||||||
|
|
||||||
//@Mixin(GeneratorOptions.class)
|
|
||||||
public class MixinGeneratorOptions {
|
public class MixinGeneratorOptions {
|
||||||
//@Inject(method = "fromProperties(Lnet/minecraft/util/registry/DynamicRegistryManager;Ljava/util/Properties;)Lnet/minecraft/world/gen/GeneratorOptions;", at = @At("HEAD"), cancellable = true)
|
@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<GeneratorOptions> cir) {
|
private static void fromProperties(DynamicRegistryManager dynamicRegistryManager, Properties properties, CallbackInfoReturnable<GeneratorOptions> cir) {
|
||||||
if(properties.get("level-type") == null) {
|
if(properties.get("level-type") == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -17,9 +17,6 @@ import net.minecraft.util.math.BlockPos;
|
|||||||
import net.minecraft.world.ServerWorldAccess;
|
import net.minecraft.world.ServerWorldAccess;
|
||||||
import net.minecraft.world.WorldAccess;
|
import net.minecraft.world.WorldAccess;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class FabricWorld implements World, FabricWorldHandle {
|
public class FabricWorld implements World, FabricWorldHandle {
|
||||||
|
|
||||||
private final Handle delegate;
|
private final Handle delegate;
|
||||||
@ -48,26 +45,11 @@ public class FabricWorld implements World, FabricWorldHandle {
|
|||||||
return delegate.world.worldProperties.getLevelName();
|
return delegate.world.worldProperties.getLevelName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public UUID getUID() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isChunkGenerated(int x, int z) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Chunk getChunkAt(int x, int z) {
|
public Chunk getChunkAt(int x, int z) {
|
||||||
return new FabricChunk(delegate.world.getChunk(x, z));
|
return new FabricChunk(delegate.world.getChunk(x, z));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public File getWorldFolder() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Block getBlockAt(int x, int y, int z) {
|
public Block getBlockAt(int x, int y, int z) {
|
||||||
BlockPos pos = new BlockPos(x, y, z);
|
BlockPos pos = new BlockPos(x, y, z);
|
||||||
|
@ -16,9 +16,6 @@ import net.minecraft.util.math.BlockPos;
|
|||||||
import net.minecraft.world.ServerWorldAccess;
|
import net.minecraft.world.ServerWorldAccess;
|
||||||
import net.minecraft.world.WorldAccess;
|
import net.minecraft.world.WorldAccess;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class FabricSeededWorldAccess implements World, FabricWorldHandle {
|
public class FabricSeededWorldAccess implements World, FabricWorldHandle {
|
||||||
|
|
||||||
private final Handle handle;
|
private final Handle handle;
|
||||||
@ -47,26 +44,11 @@ public class FabricSeededWorldAccess implements World, FabricWorldHandle {
|
|||||||
return handle.toString(); // TODO: implementation
|
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
|
@Override
|
||||||
public Chunk getChunkAt(int x, int z) {
|
public Chunk getChunkAt(int x, int z) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public File getWorldFolder() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Block getBlockAt(int x, int y, int z) {
|
public Block getBlockAt(int x, int y, int z) {
|
||||||
BlockPos pos = new BlockPos(x, y, z);
|
BlockPos pos = new BlockPos(x, y, z);
|
||||||
|
@ -16,9 +16,6 @@ import net.minecraft.world.ServerWorldAccess;
|
|||||||
import net.minecraft.world.StructureWorldAccess;
|
import net.minecraft.world.StructureWorldAccess;
|
||||||
import net.minecraft.world.WorldAccess;
|
import net.minecraft.world.WorldAccess;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class FabricWorldAccess implements World, FabricWorldHandle {
|
public class FabricWorldAccess implements World, FabricWorldHandle {
|
||||||
private final WorldAccess delegate;
|
private final WorldAccess delegate;
|
||||||
|
|
||||||
@ -46,26 +43,11 @@ public class FabricWorldAccess implements World, FabricWorldHandle {
|
|||||||
return ((ServerWorldAccess) delegate).toServerWorld().worldProperties.getLevelName();
|
return ((ServerWorldAccess) delegate).toServerWorld().worldProperties.getLevelName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public UUID getUID() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isChunkGenerated(int x, int z) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Chunk getChunkAt(int x, int z) {
|
public Chunk getChunkAt(int x, int z) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public File getWorldFolder() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Block getBlockAt(int x, int y, int z) {
|
public Block getBlockAt(int x, int y, int z) {
|
||||||
BlockPos pos = new BlockPos(x, y, z);
|
BlockPos pos = new BlockPos(x, y, z);
|
||||||
|
@ -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;"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,6 +4,7 @@
|
|||||||
"package": "com.dfsek.terra.fabric.mixin",
|
"package": "com.dfsek.terra.fabric.mixin",
|
||||||
"compatibilityLevel": "JAVA_8",
|
"compatibilityLevel": "JAVA_8",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
|
"MixinGeneratorOptions"
|
||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
"GeneratorTypeAccessor"
|
"GeneratorTypeAccessor"
|
||||||
|
136
platforms/forge/build.gradle.kts
Normal file
136
platforms/forge/build.gradle.kts
Normal file
@ -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<org.spongepowered.asm.gradle.plugins.MixinExtension> {
|
||||||
|
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<JavaCompile>().all {
|
||||||
|
options.annotationProcessorPath = files()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
val reobf = extensions.getByName<NamedDomainObjectContainer<RenameJarInPlace>>("reobf")
|
||||||
|
reobf.maybeCreate("shadowJar").run {
|
||||||
|
group = "forge"
|
||||||
|
mappings = tasks.getByName<GenerateSRG>("createMcpToSrg").output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configure<UserDevExtension> {
|
||||||
|
mappings(mapOf(
|
||||||
|
"channel" to "official",
|
||||||
|
"version" to mcVersion
|
||||||
|
))
|
||||||
|
runs {
|
||||||
|
val runConfig = Action<RunConfig> {
|
||||||
|
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<Jar>("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<com.modrinth.minotaur.TaskModrinthUpload>("publishModrinthForge") {
|
||||||
|
dependsOn("reobfShadowJar")
|
||||||
|
group = "forge"
|
||||||
|
token = System.getenv("MODRINTH_SECRET")
|
||||||
|
projectId = "FIlZB9L0"
|
||||||
|
versionNumber = project.version.toString()
|
||||||
|
uploadFile = tasks.named<RenameJarInPlace>("reobfShadowJar").get().input.absoluteFile
|
||||||
|
releaseType = "alpha"
|
||||||
|
addGameVersion("1.16.5")
|
||||||
|
addLoader("forge")
|
||||||
|
}
|
@ -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<Long, TerraWorld> 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<ConfigPack> checkedRegistry = new CheckedRegistry<>(registry);
|
||||||
|
private final AddonRegistry addonRegistry = new AddonRegistry(new ForgeAddon(this), this);
|
||||||
|
private final LockedRegistry<TerraAddon> addonLockedRegistry = new LockedRegistry<>(addonRegistry);
|
||||||
|
private final PluginConfig config = new PluginConfig();
|
||||||
|
private final Transformer<String, Biome> biomeFixer = new Transformer.Builder<String, Biome>()
|
||||||
|
.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<CommandSource, String> assemble(RequiredArgumentBuilder<CommandSource, String> in, CommandManager manager) {
|
||||||
|
return in.suggests((context, builder) -> {
|
||||||
|
List<String> 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<String> 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<String> parseCommand(String command) {
|
||||||
|
if(command.startsWith("/terra ")) command = command.substring("/terra ".length());
|
||||||
|
else if(command.startsWith("/te ")) command = command.substring("/te ".length());
|
||||||
|
List<String> c = new ArrayList<>(Arrays.asList(command.split(" ")));
|
||||||
|
if(command.endsWith(" ")) c.add("");
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void register(RegistryEvent.Register<Biome> event) {
|
||||||
|
INSTANCE.setup(); // Setup now because we need the biomes, and this event happens after blocks n stuff
|
||||||
|
INSTANCE.getConfigRegistry().forEach(pack -> pack.getBiomeRegistry().forEach((id, biome) -> event.getRegistry().register(INSTANCE.createBiome(biome)))); // Register all Terra biomes.
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void registerLevels(RegistryEvent.Register<ForgeWorldType> event) {
|
||||||
|
INSTANCE.logger().info("Registering level types...");
|
||||||
|
event.getRegistry().register(TerraLevelType.FORGE_WORLD_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void registerPop(RegistryEvent.Register<Feature<?>> event) {
|
||||||
|
event.getRegistry().register(POPULATOR_FEATURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Biome createBiome(BiomeBuilder biome) {
|
||||||
|
BiomeTemplate template = biome.getTemplate();
|
||||||
|
Map<String, Integer> 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<ConfigPack> getConfigRegistry() {
|
||||||
|
return checkedRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LockedRegistry<TerraAddon> getAddons() {
|
||||||
|
return addonLockedRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean reload() {
|
||||||
|
config.load(this);
|
||||||
|
LangUtil.load(config.getLanguage(), this); // Load language.
|
||||||
|
boolean succeed = registry.loadAll(this);
|
||||||
|
Map<Long, TerraWorld> 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<CommandSource, String> arg = argument("arg" + (max - 1), StringArgumentType.word());
|
||||||
|
for(int i = 0; i < max; i++) {
|
||||||
|
RequiredArgumentBuilder<CommandSource, String> 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<Tree> treeRegistry = event.getPack().getTreeRegistry();
|
||||||
|
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<Tree> 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<ConfigPack> 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<ConfigPack>) 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
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.forge.world.ForgeAdapter;
|
||||||
|
import net.minecraft.util.registry.Registry;
|
||||||
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class ForgeEnchantment implements Enchantment {
|
||||||
|
private final net.minecraft.enchantment.Enchantment enchantment;
|
||||||
|
|
||||||
|
public ForgeEnchantment(net.minecraft.enchantment.Enchantment enchantment) {
|
||||||
|
this.enchantment = enchantment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.enchantment.Enchantment getHandle() {
|
||||||
|
return enchantment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEnchantItem(ItemStack itemStack) {
|
||||||
|
return enchantment.canEnchant(ForgeAdapter.adapt(itemStack));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getID() {
|
||||||
|
return Objects.requireNonNull(ForgeRegistries.ENCHANTMENTS.getKey(enchantment)).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean conflictsWith(Enchantment other) {
|
||||||
|
return !enchantment.isCompatibleWith(ForgeAdapter.adapt(other));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxLevel() {
|
||||||
|
return enchantment.getMaxLevel();
|
||||||
|
}
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.dfsek.terra.forge.inventory;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.inventory.Item;
|
||||||
|
import com.dfsek.terra.api.platform.inventory.ItemStack;
|
||||||
|
|
||||||
|
public class ForgeItem implements Item {
|
||||||
|
private final net.minecraft.item.Item delegate;
|
||||||
|
|
||||||
|
public ForgeItem(net.minecraft.item.Item delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.item.Item getHandle() {
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack newItemStack(int amount) {
|
||||||
|
return new ForgeItemStack(new net.minecraft.item.ItemStack(delegate, amount));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getMaxDurability() {
|
||||||
|
return delegate.getMaxDamage();
|
||||||
|
}
|
||||||
|
}
|
@ -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<Enchantment> getEnchantments() {
|
||||||
|
return ForgeRegistries.ENCHANTMENTS.getEntries().stream().map(entry -> ForgeAdapter.adapt(entry.getValue())).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
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.forge.inventory.meta.ForgeDamageable;
|
||||||
|
import com.dfsek.terra.forge.inventory.meta.ForgeItemMeta;
|
||||||
|
|
||||||
|
public class ForgeItemStack implements ItemStack {
|
||||||
|
private net.minecraft.item.ItemStack delegate;
|
||||||
|
|
||||||
|
public ForgeItemStack(net.minecraft.item.ItemStack delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAmount() {
|
||||||
|
return delegate.getCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAmount(int i) {
|
||||||
|
delegate.setCount(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Item getType() {
|
||||||
|
return new ForgeItem(delegate.getItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemMeta getItemMeta() {
|
||||||
|
if(delegate.isDamageableItem()) return new ForgeDamageable(delegate.copy());
|
||||||
|
return new ForgeItemMeta(delegate.copy());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setItemMeta(ItemMeta meta) {
|
||||||
|
this.delegate = ((ForgeItemMeta) meta).getHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.item.ItemStack getHandle() {
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.dfsek.terra.forge.inventory.meta;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.inventory.item.Damageable;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
|
||||||
|
public class ForgeDamageable extends ForgeItemMeta implements Damageable {
|
||||||
|
public ForgeDamageable(ItemStack delegate) {
|
||||||
|
super(delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDamage() {
|
||||||
|
return delegate.getDamageValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDamage(int damage) {
|
||||||
|
delegate.setDamageValue(damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDamage() {
|
||||||
|
return delegate.isDamaged();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
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.forge.world.ForgeAdapter;
|
||||||
|
import net.minecraft.command.arguments.NBTCompoundTagArgument;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
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 ForgeItemMeta implements ItemMeta {
|
||||||
|
protected final ItemStack delegate;
|
||||||
|
|
||||||
|
public ForgeItemMeta(ItemStack delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getHandle() {
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Enchantment, Integer> getEnchantments() {
|
||||||
|
if(!delegate.isEnchanted()) return Collections.emptyMap();
|
||||||
|
Map<Enchantment, Integer> map = new HashMap<>();
|
||||||
|
|
||||||
|
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.enchant(ForgeAdapter.adapt(enchantment), level);
|
||||||
|
}
|
||||||
|
}
|
@ -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<? extends Entity> 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();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.dfsek.terra.forge.world;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.world.Biome;
|
||||||
|
|
||||||
|
public class ForgeBiome implements Biome {
|
||||||
|
private final net.minecraft.world.biome.Biome delegate;
|
||||||
|
|
||||||
|
public ForgeBiome(net.minecraft.world.biome.Biome delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.biome.Biome getHandle() {
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
}
|
@ -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"));
|
||||||
|
}
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -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<ConfigPack> 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<TerraBiomeSource> 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<Biome> biomeRegistry;
|
||||||
|
private final long seed;
|
||||||
|
private final BiomeProvider grid;
|
||||||
|
private final ConfigPack pack;
|
||||||
|
|
||||||
|
public TerraBiomeSource(Registry<Biome> 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<? extends net.minecraft.world.biome.provider.BiomeProvider> 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()))));
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<Map.Entry<Property<?>, Comparable<?>>, String> PROPERTY_MAPPER = new Function<Map.Entry<Property<?>, Comparable<?>>, String>() {
|
||||||
|
public String apply(@Nullable Map.Entry<Property<?>, Comparable<?>> entry) {
|
||||||
|
if (entry == null) {
|
||||||
|
return "<NULL>";
|
||||||
|
} else {
|
||||||
|
Property<?> property = entry.getKey();
|
||||||
|
return property.getName() + "=" + this.getName(property, entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private <T extends Comparable<T>> String getName(Property<T> 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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
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.Block;
|
||||||
|
import net.minecraft.block.Blocks;
|
||||||
|
|
||||||
|
public class ForgeBlockType implements BlockType {
|
||||||
|
private final Block delegate;
|
||||||
|
|
||||||
|
public ForgeBlockType(Block delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Block getHandle() {
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockData getDefaultData() {
|
||||||
|
return ForgeAdapter.adapt(delegate.defaultBlockState());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSolid() {
|
||||||
|
return delegate.defaultBlockState().canOcclude();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isWater() {
|
||||||
|
return delegate == Blocks.WATER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return delegate.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if(!(obj instanceof ForgeBlockType)) return false;
|
||||||
|
return ((ForgeBlockType) obj).delegate == delegate;
|
||||||
|
}
|
||||||
|
}
|
@ -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) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,159 @@
|
|||||||
|
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.state.properties.Half;
|
||||||
|
import net.minecraft.state.properties.SlabType;
|
||||||
|
import net.minecraft.state.properties.StairsShape;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
|
||||||
|
public final class ForgeEnumAdapter {
|
||||||
|
public static Stairs.Shape adapt(StairsShape 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(Half 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 StairsShape adapt(Stairs.Shape shape) {
|
||||||
|
switch(shape) {
|
||||||
|
case STRAIGHT:
|
||||||
|
return StairsShape.STRAIGHT;
|
||||||
|
case INNER_LEFT:
|
||||||
|
return StairsShape.INNER_LEFT;
|
||||||
|
case OUTER_LEFT:
|
||||||
|
return StairsShape.OUTER_LEFT;
|
||||||
|
case INNER_RIGHT:
|
||||||
|
return StairsShape.INNER_RIGHT;
|
||||||
|
case OUTER_RIGHT:
|
||||||
|
return StairsShape.OUTER_RIGHT;
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Half adapt(Bisected.Half half) {
|
||||||
|
switch(half) {
|
||||||
|
case TOP:
|
||||||
|
return Half.TOP;
|
||||||
|
case BOTTOM:
|
||||||
|
return Half.BOTTOM;
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Direction adapt(BlockFace face) {
|
||||||
|
switch(face) {
|
||||||
|
case SOUTH:
|
||||||
|
return Direction.SOUTH;
|
||||||
|
case NORTH:
|
||||||
|
return Direction.NORTH;
|
||||||
|
case EAST:
|
||||||
|
return Direction.EAST;
|
||||||
|
case WEST:
|
||||||
|
return Direction.WEST;
|
||||||
|
case UP:
|
||||||
|
return Direction.UP;
|
||||||
|
case DOWN:
|
||||||
|
return Direction.DOWN;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<BlockFace> getFaces() {
|
||||||
|
Set<BlockFace> 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<BlockFace> getAllowedFaces() {
|
||||||
|
Set<BlockFace> 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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<Direction.Axis> property;
|
||||||
|
|
||||||
|
public ForgeOrientable(BlockState delegate, EnumProperty<Direction.Axis> property) {
|
||||||
|
super(delegate);
|
||||||
|
this.property = property;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Axis> 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));
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,134 @@
|
|||||||
|
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.forge.TerraForgePlugin;
|
||||||
|
import com.dfsek.terra.forge.world.ForgeAdapter;
|
||||||
|
import net.minecraft.tileentity.MobSpawnerTileEntity;
|
||||||
|
import net.minecraft.util.registry.Registry;
|
||||||
|
import net.minecraft.world.IWorld;
|
||||||
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class ForgeMobSpawner extends ForgeBlockState implements MobSpawner { // TODO: finish implementation / refactor API because bukkit doesnt expose most of the stuff spawners can do
|
||||||
|
|
||||||
|
|
||||||
|
public ForgeMobSpawner(MobSpawnerTileEntity blockEntity, IWorld worldAccess) {
|
||||||
|
super(blockEntity, worldAccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityType getSpawnedType() {
|
||||||
|
return ForgeAdapter.adapt(ForgeRegistries.ENTITIES.getValue(((MobSpawnerTileEntity) blockEntity).getSpawner().getSpawnerEntity().getType().getRegistryName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSpawnedType(@NotNull EntityType creatureType) {
|
||||||
|
((MobSpawnerTileEntity) blockEntity).getSpawner().setEntityId(ForgeAdapter.adapt(creatureType));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDelay() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDelay(int delay) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinSpawnDelay() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMinSpawnDelay(int delay) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxSpawnDelay() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMaxSpawnDelay(int delay) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSpawnCount() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSpawnCount(int spawnCount) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxNearbyEntities() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMaxNearbyEntities(int maxNearbyEntities) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRequiredPlayerRange() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRequiredPlayerRange(int requiredPlayerRange) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSpawnRange() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSpawnRange(int spawnRange) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyState(String state) {
|
||||||
|
SerialState.parse(state).forEach((k, v) -> {
|
||||||
|
switch(k) {
|
||||||
|
case "type":
|
||||||
|
setSpawnedType(TerraForgePlugin.getInstance().getWorldHandle().getEntity(v));
|
||||||
|
return;
|
||||||
|
case "delay":
|
||||||
|
setDelay(Integer.parseInt(v));
|
||||||
|
return;
|
||||||
|
case "min_delay":
|
||||||
|
setMinSpawnDelay(Integer.parseInt(v));
|
||||||
|
return;
|
||||||
|
case "max_delay":
|
||||||
|
setMaxSpawnDelay(Integer.parseInt(v));
|
||||||
|
return;
|
||||||
|
case "spawn_count":
|
||||||
|
setSpawnCount(Integer.parseInt(v));
|
||||||
|
return;
|
||||||
|
case "spawn_range":
|
||||||
|
setSpawnRange(Integer.parseInt(v));
|
||||||
|
return;
|
||||||
|
case "max_nearby":
|
||||||
|
setMaxNearbyEntities(Integer.parseInt(v));
|
||||||
|
return;
|
||||||
|
case "required_player_range":
|
||||||
|
setRequiredPlayerRange(Integer.parseInt(v));
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Invalid property: " + k);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
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.tileentity.SignTileEntity;
|
||||||
|
import net.minecraft.util.text.StringTextComponent;
|
||||||
|
import net.minecraft.world.IWorld;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class ForgeSign extends ForgeBlockState implements Sign {
|
||||||
|
public ForgeSign(SignTileEntity blockEntity, IWorld worldAccess) {
|
||||||
|
super(blockEntity, worldAccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String[] getLines() {
|
||||||
|
SignTileEntity sign = (SignTileEntity) blockEntity;
|
||||||
|
|
||||||
|
return new String[] {
|
||||||
|
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 ((SignTileEntity) blockEntity).getMessage(index).getString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException {
|
||||||
|
((SignTileEntity) blockEntity).setMessage(index, new StringTextComponent(line));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyState(String state) {
|
||||||
|
SerialState.parse(state).forEach((k, v) -> {
|
||||||
|
if(!k.startsWith("text")) throw new IllegalArgumentException("Invalid property: " + k);
|
||||||
|
setLine(Integer.parseInt(k.substring(4)), v);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.dfsek.terra.forge.world.entity;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.entity.EntityType;
|
||||||
|
|
||||||
|
public class ForgeEntityType implements EntityType {
|
||||||
|
private final net.minecraft.entity.EntityType<?> type;
|
||||||
|
|
||||||
|
public ForgeEntityType(net.minecraft.entity.EntityType<?> type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.entity.EntityType<?> getHandle() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
@ -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<NoFeatureConfig> {
|
||||||
|
public PopulatorFeature(Codec<NoFeatureConfig> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
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.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 ForgeChunkData implements ChunkData {
|
||||||
|
private final IChunk handle;
|
||||||
|
|
||||||
|
public ForgeChunkData(IChunk handle) {
|
||||||
|
this.handle = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IChunk getHandle() {
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxHeight() {
|
||||||
|
return handle.getMaxBuildHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlock(int x, int y, int z, @NotNull BlockData blockData) {
|
||||||
|
handle.setBlockState(new BlockPos(x, y, z), ((ForgeBlockData) blockData).getHandle(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull BlockData getBlockData(int x, int y, int z) {
|
||||||
|
return new ForgeBlockData(handle.getBlockState(new BlockPos(x, y, z)));
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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<ConfigPack> 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<ForgeChunkGeneratorWrapper> 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<? extends ChunkGenerator> 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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<Biome> biomeRegistry, Registry<DimensionSettings> 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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
package com.dfsek.terra.forge.world.handles;
|
||||||
|
|
||||||
|
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.handles.chunk.ForgeChunk;
|
||||||
|
import com.dfsek.terra.forge.world.handles.world.ForgeWorldHandle;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.IServerWorld;
|
||||||
|
import net.minecraft.world.server.ServerWorld;
|
||||||
|
|
||||||
|
public class ForgeWorld implements World, ForgeWorldHandle {
|
||||||
|
|
||||||
|
private final Handle delegate;
|
||||||
|
|
||||||
|
public ForgeWorld(ServerWorld world, ChunkGenerator generator) {
|
||||||
|
this.delegate = new Handle(world, generator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getSeed() {
|
||||||
|
return delegate.world.getSeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxHeight() {
|
||||||
|
return delegate.world.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChunkGenerator getGenerator() {
|
||||||
|
return delegate.generator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return delegate.world.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Chunk getChunkAt(int x, int z) {
|
||||||
|
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 ForgeBlock(pos, delegate.world);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return ((IServerWorld) delegate.world).getLevel().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
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 = ForgeAdapter.adapt(entityType).create(delegate.world);
|
||||||
|
entity.setPos(location.getX(), location.getY(), location.getZ());
|
||||||
|
delegate.world.addFreshEntity(entity);
|
||||||
|
return new ForgeEntity(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinHeight() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Handle getHandle() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServerWorld getWorld() {
|
||||||
|
return delegate.getWorld();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Handle {
|
||||||
|
private final ServerWorld world;
|
||||||
|
private final ChunkGenerator generator;
|
||||||
|
|
||||||
|
private Handle(ServerWorld world, ChunkGenerator generator) {
|
||||||
|
this.world = world;
|
||||||
|
this.generator = generator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChunkGenerator getGenerator() {
|
||||||
|
return generator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerWorld getWorld() {
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
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.forge.world.block.ForgeBlockData;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class ForgeChunk implements Chunk {
|
||||||
|
private final net.minecraft.world.chunk.Chunk chunk;
|
||||||
|
|
||||||
|
public ForgeChunk(net.minecraft.world.chunk.Chunk chunk) {
|
||||||
|
this.chunk = chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getX() {
|
||||||
|
return chunk.getPos().x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getZ() {
|
||||||
|
return chunk.getPos().z;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public World getWorld() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Block getBlock(int x, int y, int z) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.chunk.Chunk getHandle() {
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlock(int x, int y, int z, @NotNull BlockData blockData) {
|
||||||
|
chunk.setBlockState(new BlockPos(x, y, z), ((ForgeBlockData) blockData).getHandle(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull BlockData getBlockData(int x, int y, int z) {
|
||||||
|
return getBlock(x, y, z).getBlockData();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
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.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.IWorld;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class ForgeChunkWorldAccess implements Chunk {
|
||||||
|
private final IWorld chunkRegion;
|
||||||
|
private final int x;
|
||||||
|
private final int z;
|
||||||
|
|
||||||
|
public ForgeChunkWorldAccess(IWorld chunkRegion, int x, int z) {
|
||||||
|
this.chunkRegion = chunkRegion;
|
||||||
|
this.x = x << 4;
|
||||||
|
this.z = z << 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getX() {
|
||||||
|
return x >> 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getZ() {
|
||||||
|
return z >> 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public World getWorld() {
|
||||||
|
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 ForgeBlock(pos, chunkRegion);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IWorld getHandle() {
|
||||||
|
return chunkRegion;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlock(int x, int y, int z, @NotNull BlockData blockData) {
|
||||||
|
chunkRegion.setBlock(new BlockPos(x + this.x, y, z + this.z), ((ForgeBlockData) blockData).getHandle(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull BlockData getBlockData(int x, int y, int z) {
|
||||||
|
return getBlock(x, y, z).getBlockData();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,115 @@
|
|||||||
|
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 String getName() {
|
||||||
|
return handle.toString(); // TODO: implementation
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
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 String getName() {
|
||||||
|
return ((IServerWorld) delegate).getLevel().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.dfsek.terra.forge.world.handles.world;
|
||||||
|
|
||||||
|
import net.minecraft.world.IWorld;
|
||||||
|
|
||||||
|
public interface ForgeWorldHandle {
|
||||||
|
IWorld getWorld();
|
||||||
|
}
|
17
platforms/forge/src/main/resources/META-INF/mods.toml
Normal file
17
platforms/forge/src/main/resources/META-INF/mods.toml
Normal file
@ -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"
|
6
platforms/forge/src/main/resources/pack.mcmeta
Normal file
6
platforms/forge/src/main/resources/pack.mcmeta
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"pack": {
|
||||||
|
"description": "Terra Resources",
|
||||||
|
"pack_format": 6
|
||||||
|
}
|
||||||
|
}
|
14
platforms/forge/src/main/resources/terra.mixins.json
Normal file
14
platforms/forge/src/main/resources/terra.mixins.json
Normal file
@ -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"
|
||||||
|
}
|
20
platforms/forge/src/test/resources/META-INF/mods.toml
Normal file
20
platforms/forge/src/test/resources/META-INF/mods.toml
Normal file
@ -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"
|
6
platforms/forge/src/test/resources/pack.mcmeta
Normal file
6
platforms/forge/src/test/resources/pack.mcmeta
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"pack": {
|
||||||
|
"description": "Terra resources",
|
||||||
|
"pack_format": 6
|
||||||
|
}
|
||||||
|
}
|
@ -19,7 +19,6 @@ import java.io.IOException;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class DirectWorld implements World {
|
public class DirectWorld implements World {
|
||||||
private final long seed;
|
private final long seed;
|
||||||
@ -51,16 +50,6 @@ public class DirectWorld implements World {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public UUID getUID() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isChunkGenerated(int x, int z) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Chunk getChunkAt(int x, int z) {
|
public Chunk getChunkAt(int x, int z) {
|
||||||
MCAFile file = compute(x, z);
|
MCAFile file = compute(x, z);
|
||||||
@ -72,11 +61,6 @@ public class DirectWorld implements World {
|
|||||||
return new DirectChunkData(chunk, this, x, z);
|
return new DirectChunkData(chunk, this, x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public File getWorldFolder() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Block getBlockAt(int x, int y, int z) {
|
public Block getBlockAt(int x, int y, int z) {
|
||||||
return new DirectBlock(this, new Vector3(x, y, z));
|
return new DirectBlock(this, new Vector3(x, y, z));
|
||||||
|
@ -13,6 +13,7 @@ include("platforms:bukkit")
|
|||||||
include("platforms:fabric")
|
include("platforms:fabric")
|
||||||
include("platforms:region")
|
include("platforms:region")
|
||||||
include("platforms:sponge")
|
include("platforms:sponge")
|
||||||
|
include("platforms:forge")
|
||||||
|
|
||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user