remove Forge implementation

This commit is contained in:
dfsek 2021-08-29 17:20:34 -07:00
parent 1c124e8b75
commit 859b968555
60 changed files with 0 additions and 3346 deletions

View File

@ -1,138 +0,0 @@
import com.dfsek.terra.configureCommon
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import net.minecraftforge.gradle.common.util.RunConfig
import net.minecraftforge.gradle.userdev.UserDevExtension
import net.minecraftforge.gradle.userdev.tasks.RenameJarInPlace
buildscript {
repositories {
maven { url = uri("https://files.minecraftforge.net/maven") }
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 {
id("com.modrinth.minotaur").version("1.1.0")
}
configureCommon()
repositories {
maven { url = uri("https://files.minecraftforge.net/maven") }
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()
}
}
}
tasks.named<ShadowJar>("shadowJar") {
archiveBaseName.set(tasks.getByName<Jar>("jar").archiveBaseName.orNull) // Pain. Agony, even.
archiveClassifier.set("") // Suffering, if you will.
}
afterEvaluate {
tasks.named<RenameJarInPlace>("reobfJar") {
val shadow = tasks.getByName<ShadowJar>("shadowJar");
dependsOn(shadow)
input = shadow.archiveFile.orNull?.asFile
}
}
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("reobfJar")
group = "forge"
token = System.getenv("MODRINTH_SECRET")
projectId = "FIlZB9L0"
versionNumber = "${project.version}-forge"
uploadFile = tasks.named<RenameJarInPlace>("reobfJar").get().input.absoluteFile
releaseType = "alpha"
addGameVersion("1.16.5")
addLoader("forge")
}

View File

@ -1,90 +0,0 @@
package com.dfsek.terra.forge;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.block.BlockFace;
import com.dfsek.terra.api.block.entity.Container;
import com.dfsek.terra.api.block.entity.MobSpawner;
import com.dfsek.terra.api.block.entity.Sign;
import com.dfsek.terra.forge.block.ForgeBlockData;
import com.dfsek.terra.forge.block.data.ForgeDirectional;
import com.dfsek.terra.forge.block.data.ForgeMultipleFacing;
import com.dfsek.terra.forge.block.data.ForgeOrientable;
import com.dfsek.terra.forge.block.data.ForgeRotatable;
import com.dfsek.terra.forge.block.data.ForgeSlab;
import com.dfsek.terra.forge.block.data.ForgeStairs;
import com.dfsek.terra.forge.block.data.ForgeWaterlogged;
import net.minecraft.block.BlockState;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.LockableLootTileEntity;
import net.minecraft.tileentity.MobSpawnerTileEntity;
import net.minecraft.tileentity.SignTileEntity;
import net.minecraft.tileentity.TileEntity;
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 com.dfsek.terra.api.block.entity.BlockState adapt(com.dfsek.terra.api.block.Block block) {
IWorld worldAccess = (IWorld) block.getLocation().getWorld();
TileEntity entity = worldAccess.getBlockEntity(adapt(block.getLocation().toVector()));
if(entity instanceof SignTileEntity) {
return (Sign) entity;
} else if(entity instanceof MobSpawnerTileEntity) {
return (MobSpawner) entity;
} else if(entity instanceof LockableLootTileEntity) {
return (Container) entity;
}
return null;
}
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);
}
}
}

View File

@ -1,109 +0,0 @@
package com.dfsek.terra.forge;
import com.dfsek.terra.api.util.generic.pair.Pair;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.forge.config.PostLoadCompatibilityOptions;
import com.dfsek.terra.forge.config.PreLoadCompatibilityOptions;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.WorldGenRegistries;
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.carver.ConfiguredCarver;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.StructureFeature;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import java.util.function.Supplier;
public final class ForgeUtil {
public static String createBiomeID(ConfigPack pack, String biomeID) {
return pack.getTemplate().getID().toLowerCase() + "/" + biomeID.toLowerCase(Locale.ROOT);
}
public static Biome createBiome(BiomeBuilder biome, ConfigPack pack, TerraForgePlugin.ForgeAddon forgeAddon) {
BiomeTemplate template = biome.getTemplate();
Map<String, Integer> colors = template.getColors();
Biome vanilla = (Biome) (new ArrayList<>(biome.getVanillaBiomes().getContents()).get(0)).getHandle();
BiomeGenerationSettings.Builder generationSettings = new BiomeGenerationSettings.Builder();
generationSettings.surfaceBuilder(vanilla.getGenerationSettings().getSurfaceBuilder()); // It needs a surfacebuilder, even though we dont use it.
generationSettings.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, TerraForgePlugin.POPULATOR_CONFIGURED_FEATURE);
if(pack.getTemplate().vanillaCaves()) {
for(GenerationStage.Carving carver : GenerationStage.Carving.values()) {
for(Supplier<ConfiguredCarver<?>> configuredCarverSupplier : vanilla.getGenerationSettings().getCarvers(carver)) {
generationSettings.addCarver(carver, configuredCarverSupplier.get());
}
}
}
Pair<PreLoadCompatibilityOptions, PostLoadCompatibilityOptions> pair = forgeAddon.getTemplates().get(pack);
PreLoadCompatibilityOptions compatibilityOptions = pair.getLeft();
PostLoadCompatibilityOptions postLoadCompatibilityOptions = pair.getRight();
TerraForgePlugin.getInstance().getDebugLogger().info("Injecting Vanilla structures and features into Terra biome " + biome.getTemplate().getID());
for(Supplier<StructureFeature<?, ?>> structureFeature : vanilla.getGenerationSettings().structures()) {
ResourceLocation key = WorldGenRegistries.CONFIGURED_STRUCTURE_FEATURE.getKey(structureFeature.get());
if(!compatibilityOptions.getExcludedBiomeStructures().contains(key) && !postLoadCompatibilityOptions.getExcludedPerBiomeStructures().getOrDefault(biome, Collections.emptySet()).contains(key)) {
generationSettings.addStructureStart(structureFeature.get());
TerraForgePlugin.getInstance().getDebugLogger().info("Injected structure " + key);
}
}
if(compatibilityOptions.doBiomeInjection()) {
for(int step = 0; step < vanilla.getGenerationSettings().features().size(); step++) {
for(Supplier<ConfiguredFeature<?, ?>> featureSupplier : vanilla.getGenerationSettings().features().get(step)) {
ResourceLocation key = WorldGenRegistries.CONFIGURED_FEATURE.getKey(featureSupplier.get());
if(!compatibilityOptions.getExcludedBiomeFeatures().contains(key) && !postLoadCompatibilityOptions.getExcludedPerBiomeFeatures().getOrDefault(biome, Collections.emptySet()).contains(key)) {
generationSettings.addFeature(step, featureSupplier);
TerraForgePlugin.getInstance().getDebugLogger().info("Injected feature " + key + " at stage " + step);
}
}
}
}
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);
}
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()));
}
}

View File

@ -1,408 +0,0 @@
package com.dfsek.terra.forge;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.TypeRegistry;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.addons.TerraAddon;
import com.dfsek.terra.api.addon.annotations.Addon;
import com.dfsek.terra.api.addon.annotations.Author;
import com.dfsek.terra.api.addon.annotations.Version;
import com.dfsek.terra.api.command.CommandManager;
import com.dfsek.terra.api.command.TerraCommandManager;
import com.dfsek.terra.api.command.exception.MalformedCommandException;
import com.dfsek.terra.api.event.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.ConfigPackPostLoadEvent;
import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.block.BlockData;
import com.dfsek.terra.api.handle.ItemHandle;
import com.dfsek.terra.api.handle.WorldHandle;
import com.dfsek.terra.api.world.Tree;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.LockedRegistry;
import com.dfsek.terra.api.transform.Transformer;
import com.dfsek.terra.api.transform.Validator;
import com.dfsek.terra.api.util.JarUtil;
import com.dfsek.terra.api.util.generic.pair.Pair;
import com.dfsek.terra.api.util.logging.DebugLogger;
import com.dfsek.terra.commands.CommandUtil;
import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.PluginConfig;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.config.lang.Language;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.forge.config.PostLoadCompatibilityOptions;
import com.dfsek.terra.forge.config.PreLoadCompatibilityOptions;
import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper;
import com.dfsek.terra.forge.generation.PopulatorFeature;
import com.dfsek.terra.forge.generation.TerraBiomeSource;
import com.dfsek.terra.forge.handle.ForgeItemHandle;
import com.dfsek.terra.forge.handle.ForgeWorldHandle;
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 net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.WorldGenRegistries;
import net.minecraft.world.DimensionType;
import net.minecraft.world.IWorld;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.feature.ConfiguredFeature;
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.server.ServerWorld;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.ForgeRegistry;
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.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.jar.JarFile;
import java.util.zip.ZipFile;
@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<DimensionType, Pair<ServerWorld, 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 ForgeAddon addon = new ForgeAddon(this);
private final AddonRegistry addonRegistry = new AddonRegistry(addon, 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)), Validator.notNull())
.addTransform(id -> ForgeRegistries.BIOMES.getValue(ResourceLocation.tryParse("minecraft:" + id.toLowerCase())), Validator.notNull()).build();
private final File dataFolder;
public TerraForgePlugin() {
if(INSTANCE != null) throw new IllegalStateException("Only one TerraPlugin instance may exist.");
INSTANCE = this;
this.dataFolder = Paths.get("config", "Terra").toFile();
saveDefaultConfig();
config.load(this);
debugLogger.setDebug(config.isDebug());
LangUtil.load(config.getLanguage(), this);
try {
CommandUtil.registerAll(manager);
} catch(MalformedCommandException e) {
e.printStackTrace(); // TODO do something here even though this should literally never happen
}
}
public static TerraForgePlugin getInstance() {
return INSTANCE;
}
@SubscribeEvent
public static void setupListener(FMLCommonSetupEvent event) {
event.enqueueWork(() -> {
Registry.register(Registry.BIOME_SOURCE, "terra:biome", TerraBiomeSource.CODEC);
Registry.register(Registry.CHUNK_GENERATOR, "terra:generator", ForgeChunkGeneratorWrapper.CODEC);
});
}
public void init() {
logger.info("Initializing Terra...");
if(!addonRegistry.loadAll()) {
throw new IllegalStateException("Failed to load addons. Please correct com.dfsek.terra.addon installations to continue.");
}
logger.info("Loaded addons.");
registry.loadAll(this);
logger.info("Loaded packs.");
((ForgeRegistry<Biome>) ForgeRegistries.BIOMES).unfreeze(); // Evil
getConfigRegistry().forEach(pack -> pack.getBiomeRegistry().forEach((id, biome) -> ForgeRegistries.BIOMES.register(ForgeUtil.createBiome(biome, pack, addon)))); // Register all Terra biomes.
((ForgeRegistry<Biome>) ForgeRegistries.BIOMES).freeze();
}
@Override
public WorldHandle getWorldHandle() {
return worldHandle;
}
@Override
public TerraWorld getWorld(World world) {
return getWorld(((IWorld) world).dimensionType());
}
public TerraWorld getWorld(DimensionType type) {
TerraWorld world = worldMap.get(type).getRight();
if(world == null) throw new IllegalArgumentException("No world exists with dimension type " + type);
return world;
}
/**
* evil code brought to you by Forge Mod Loader
* <p>
* Forge changes the JAR URI to something that cannot
* be resolved back to the original JAR, so we have to
* do this to get our JAR.
*/
@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();
}
@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 config.isDebug();
}
@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);
worldMap.forEach((seed, pair) -> {
pair.getRight().getConfig().getSamplerCache().clear();
String packID = pair.getRight().getConfig().getTemplate().getID();
pair.setRight(new TerraWorld(pair.getRight().getWorld(), registry.get(packID), this));
});
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.world.Biome.class, (t, o, l) -> biomeFixer.translate((String) o))
.registerLoader(ResourceLocation.class, (t, o, l) -> {
ResourceLocation identifier = ResourceLocation.tryParse((String) o);
if(identifier == null) throw new LoadException("Invalid identifier: " + o);
return identifier;
});
}
@Override
public EventManager getEventManager() {
return eventManager;
}
@Override
public Profiler getProfiler() {
return profiler;
}
public CommandManager getManager() {
return manager;
}
public Map<DimensionType, Pair<ServerWorld, TerraWorld>> getWorldMap() {
return worldMap;
}
@Addon("Terra-Forge")
@Author("Terra")
@Version("1.0.0")
public static final class ForgeAddon extends TerraAddon implements EventListener {
private final Map<ConfigPack, Pair<PreLoadCompatibilityOptions, PostLoadCompatibilityOptions>> templates = new HashMap<>();
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().getRegistry(Tree.class);
injectTree(treeRegistry, "BROWN_MUSHROOM", Features.HUGE_BROWN_MUSHROOM);
injectTree(treeRegistry, "RED_MUSHROOM", Features.HUGE_RED_MUSHROOM);
injectTree(treeRegistry, "JUNGLE", Features.MEGA_JUNGLE_TREE);
injectTree(treeRegistry, "JUNGLE_COCOA", Features.JUNGLE_TREE);
injectTree(treeRegistry, "LARGE_OAK", Features.FANCY_OAK);
injectTree(treeRegistry, "LARGE_SPRUCE", Features.PINE);
injectTree(treeRegistry, "SMALL_JUNGLE", Features.JUNGLE_TREE);
injectTree(treeRegistry, "SWAMP_OAK", Features.SWAMP_TREE);
injectTree(treeRegistry, "TALL_BIRCH", Features.BIRCH_TALL);
injectTree(treeRegistry, "ACACIA", Features.ACACIA);
injectTree(treeRegistry, "BIRCH", Features.BIRCH);
injectTree(treeRegistry, "DARK_OAK", Features.DARK_OAK);
injectTree(treeRegistry, "OAK", Features.OAK);
injectTree(treeRegistry, "CHORUS_PLANT", Features.CHORUS_PLANT);
injectTree(treeRegistry, "SPRUCE", Features.SPRUCE);
injectTree(treeRegistry, "JUNGLE_BUSH", Features.JUNGLE_BUSH);
injectTree(treeRegistry, "MEGA_SPRUCE", Features.MEGA_SPRUCE);
injectTree(treeRegistry, "CRIMSON_FUNGUS", Features.CRIMSON_FUNGI);
injectTree(treeRegistry, "WARPED_FUNGUS", Features.WARPED_FUNGI);
PreLoadCompatibilityOptions template = new PreLoadCompatibilityOptions();
try {
event.loadTemplate(template);
} catch(ConfigException e) {
e.printStackTrace();
}
if(template.doRegistryInjection()) {
WorldGenRegistries.CONFIGURED_FEATURE.entrySet().forEach(entry -> {
if(!template.getExcludedRegistryFeatures().contains(entry.getKey().getRegistryName())) {
try {
event.getPack().getTreeRegistry().add(entry.getKey().getRegistryName().toString(), (Tree) entry.getValue());
main.getDebugLogger().info("Injected ConfiguredFeature " + entry.getKey().getRegistryName() + " as Tree: " + entry.getValue());
} catch(DuplicateEntryException ignored) {
}
}
});
}
templates.put(event.getPack(), Pair.of(template, null));
}
@Priority(Priority.HIGHEST)
@Global
public void createInjectionOptions(ConfigPackPostLoadEvent event) {
PostLoadCompatibilityOptions template = new PostLoadCompatibilityOptions();
try {
event.loadTemplate(template);
} catch(ConfigException e) {
e.printStackTrace();
}
templates.get(event.getPack()).setRight(template);
}
private void injectTree(CheckedRegistry<Tree> registry, String id, ConfiguredFeature<?, ?> tree) {
try {
registry.add(id, (Tree) tree);
} catch(DuplicateEntryException ignore) {
}
}
public Map<ConfigPack, Pair<PreLoadCompatibilityOptions, PostLoadCompatibilityOptions>> getTemplates() {
return templates;
}
}
}

View File

@ -1,95 +0,0 @@
package com.dfsek.terra.forge.block;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.block.Block;
import com.dfsek.terra.api.block.BlockData;
import com.dfsek.terra.api.block.BlockFace;
import com.dfsek.terra.api.block.BlockType;
import com.dfsek.terra.api.block.entity.BlockState;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.forge.ForgeAdapter;
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 ForgeAdapter.adapt(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((World) 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;
}
}
}

View File

@ -1,83 +0,0 @@
package com.dfsek.terra.forge.block;
import com.dfsek.terra.api.block.BlockData;
import com.dfsek.terra.api.block.BlockType;
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 (BlockType) 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;
}
}

View File

@ -1,29 +0,0 @@
package com.dfsek.terra.forge.block.data;
import com.dfsek.terra.api.block.data.AnaloguePowerable;
import com.dfsek.terra.forge.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) {
}
}

View File

@ -1,42 +0,0 @@
package com.dfsek.terra.forge.block.data;
import com.dfsek.terra.api.block.BlockFace;
import com.dfsek.terra.api.block.data.Directional;
import com.dfsek.terra.forge.ForgeAdapter;
import com.dfsek.terra.forge.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));
}
}

View File

@ -1,159 +0,0 @@
package com.dfsek.terra.forge.block.data;
import com.dfsek.terra.api.block.Axis;
import com.dfsek.terra.api.block.BlockFace;
import com.dfsek.terra.api.block.data.Bisected;
import com.dfsek.terra.api.block.data.Slab;
import com.dfsek.terra.api.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();
}
}
}

View File

@ -1,69 +0,0 @@
package com.dfsek.terra.forge.block.data;
import com.dfsek.terra.api.block.BlockFace;
import com.dfsek.terra.api.block.data.MultipleFacing;
import com.dfsek.terra.forge.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);
}
}

View File

@ -1,36 +0,0 @@
package com.dfsek.terra.forge.block.data;
import com.dfsek.terra.api.block.Axis;
import com.dfsek.terra.api.block.data.Orientable;
import com.dfsek.terra.forge.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));
}
}

View File

@ -1,111 +0,0 @@
package com.dfsek.terra.forge.block.data;
import com.dfsek.terra.api.block.BlockFace;
import com.dfsek.terra.api.block.data.Rotatable;
import com.dfsek.terra.forge.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;
}
}
}

View File

@ -1,21 +0,0 @@
package com.dfsek.terra.forge.block.data;
import com.dfsek.terra.api.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));
}
}

View File

@ -1,42 +0,0 @@
package com.dfsek.terra.forge.block.data;
import com.dfsek.terra.api.block.BlockFace;
import com.dfsek.terra.api.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));
}
}

View File

@ -1,22 +0,0 @@
package com.dfsek.terra.forge.block.data;
import com.dfsek.terra.api.block.data.Waterlogged;
import com.dfsek.terra.forge.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);
}
}

View File

@ -1,30 +0,0 @@
package com.dfsek.terra.forge.config;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.config.builder.BiomeBuilder;
import net.minecraft.util.ResourceLocation;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@SuppressWarnings("FieldMayBeFinal")
public class PostLoadCompatibilityOptions implements ConfigTemplate {
@Value("structures.inject-biome.exclude-biomes")
@Default
private Map<BiomeBuilder, Set<ResourceLocation>> excludedPerBiomeStructures = new HashMap<>();
@Value("features.inject-biome.exclude-biomes")
@Default
private Map<BiomeBuilder, Set<ResourceLocation>> excludedPerBiomeFeatures = new HashMap<>();
public Map<BiomeBuilder, Set<ResourceLocation>> getExcludedPerBiomeFeatures() {
return excludedPerBiomeFeatures;
}
public Map<BiomeBuilder, Set<ResourceLocation>> getExcludedPerBiomeStructures() {
return excludedPerBiomeStructures;
}
}

View File

@ -1,52 +0,0 @@
package com.dfsek.terra.forge.config;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ConfigTemplate;
import net.minecraft.util.ResourceLocation;
import java.util.HashSet;
import java.util.Set;
@SuppressWarnings("FieldMayBeFinal")
public class PreLoadCompatibilityOptions implements ConfigTemplate {
@Value("features.inject-registry.enable")
@Default
private boolean doRegistryInjection = false;
@Value("features.inject-biome.enable")
@Default
private boolean doBiomeInjection = false;
@Value("features.inject-registry.excluded-features")
@Default
private Set<ResourceLocation> excludedRegistryFeatures = new HashSet<>();
@Value("features.inject-biome.excluded-features")
@Default
private Set<ResourceLocation> excludedBiomeFeatures = new HashSet<>();
@Value("structures.inject-biome.excluded-features")
@Default
private Set<ResourceLocation> excludedBiomeStructures = new HashSet<>();
public boolean doBiomeInjection() {
return doBiomeInjection;
}
public boolean doRegistryInjection() {
return doRegistryInjection;
}
public Set<ResourceLocation> getExcludedBiomeFeatures() {
return excludedBiomeFeatures;
}
public Set<ResourceLocation> getExcludedRegistryFeatures() {
return excludedRegistryFeatures;
}
public Set<ResourceLocation> getExcludedBiomeStructures() {
return excludedBiomeStructures;
}
}

View File

@ -1,197 +0,0 @@
package com.dfsek.terra.forge.generation;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.generator.ChunkData;
import com.dfsek.terra.api.world.generator.GeneratorWrapper;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.api.world.locate.AsyncStructureFinder;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.forge.ForgeAdapter;
import com.dfsek.terra.forge.TerraForgePlugin;
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.dfsek.terra.world.population.items.TerraStructure;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.jafama.FastMath;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.util.SharedSeedRandom;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.registry.DynamicRegistries;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.Blockreader;
import net.minecraft.world.DimensionType;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.BiomeManager;
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.Structure;
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.server.ServerWorld;
import net.minecraft.world.spawner.WorldEntitySpawner;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class ForgeChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper {
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 long seed;
private final DefaultChunkGenerator3D delegate;
private final TerraBiomeSource biomeSource;
private final ConfigPack pack;
private DimensionType dimensionType;
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;
}
public ConfigPack getPack() {
return pack;
}
@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_) {
}
@Nullable
@Override
public BlockPos findNearestMapFeature(@NotNull ServerWorld world, @NotNull Structure<?> feature, @NotNull BlockPos center, int radius, boolean skipExistingChunks) {
if(!pack.getTemplate().disableStructures()) {
String name = Objects.requireNonNull(Registry.STRUCTURE_FEATURE.getKey(feature)).toString();
TerraWorld terraWorld = TerraForgePlugin.getInstance().getWorld((World) world);
TerraStructure located = pack.getStructure(pack.getTemplate().getLocatable().get(name));
if(located != null) {
CompletableFuture<BlockPos> result = new CompletableFuture<>();
AsyncStructureFinder finder = new AsyncStructureFinder(terraWorld.getBiomeProvider(), located, ForgeAdapter.adapt(center).toLocation((World) world), 0, 500, location -> {
result.complete(ForgeAdapter.adapt(location));
}, TerraForgePlugin.getInstance());
finder.run(); // Do this synchronously.
try {
return result.get();
} catch(InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
}
return super.findNearestMapFeature(world, feature, center, radius, skipExistingChunks);
}
@Override
public boolean hasStronghold(@NotNull ChunkPos p_235952_1_) {
if(pack.getTemplate().vanillaStructures()) return super.hasStronghold(p_235952_1_);
return false;
}
@Override
public void createStructures(@NotNull DynamicRegistries dynamicRegistries, @NotNull StructureManager manager, @NotNull IChunk chunk, @NotNull TemplateManager templateManager, long p_242707_5_) {
if(pack.getTemplate().vanillaStructures()) super.createStructures(dynamicRegistries, manager, chunk, templateManager, p_242707_5_);
}
@Override
public void applyCarvers(long p_230350_1_, @NotNull BiomeManager biomeManager, @NotNull IChunk chunk, GenerationStage.@NotNull Carving carving) {
if(pack.getTemplate().vanillaCaves()) super.applyCarvers(p_230350_1_, biomeManager, chunk, carving);
}
@Override
public void fillFromNoise(@NotNull IWorld world, @NotNull StructureManager p_230352_2_, @NotNull IChunk chunk) {
delegate.generateChunkData((World) world, new FastRandom(), chunk.getPos().x, chunk.getPos().z, (ChunkData) chunk);
}
@Override
public int getBaseHeight(int x, int z, Heightmap.@NotNull Type p_222529_3_) {
TerraWorld world = TerraForgePlugin.getInstance().getWorld(dimensionType);
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 x, int z) {
TerraWorld world = TerraForgePlugin.getInstance().getWorld(dimensionType);
int height = getBaseHeight(x, z, Heightmap.Type.WORLD_SURFACE);
BlockState[] array = new BlockState[256];
for(int y = 255; y >= 0; y--) {
if(y > height) {
if(y > ((UserDefinedBiome) world.getBiomeProvider().getBiome(x, z)).getConfig().getSeaLevel()) {
array[y] = Blocks.AIR.defaultBlockState();
} else {
array[y] = Blocks.WATER.defaultBlockState();
}
} else {
array[y] = Blocks.STONE.defaultBlockState();
}
}
return new Blockreader(array);
}
@Override
public void spawnOriginalMobs(WorldGenRegion region) {
if(pack.getTemplate().vanillaMobs()) {
int cx = region.getCenterX();
int cy = region.getCenterZ();
Biome biome = region.getBiome((new ChunkPos(cx, cy)).getWorldPosition());
SharedSeedRandom chunkRandom = new SharedSeedRandom();
chunkRandom.setDecorationSeed(region.getSeed(), cx << 4, cy << 4);
WorldEntitySpawner.spawnMobsForChunkGeneration(region, biome, cx, cy, chunkRandom);
}
}
@Override
public TerraChunkGenerator getHandle() {
return delegate;
}
public void setDimensionType(DimensionType dimensionType) {
this.dimensionType = dimensionType;
}
}

View File

@ -1,30 +0,0 @@
package com.dfsek.terra.forge.generation;
import com.dfsek.terra.api.world.Chunk;
import com.dfsek.terra.api.world.World;
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, @NotNull BlockPos pos, @NotNull NoFeatureConfig config) {
ForgeChunkGeneratorWrapper gen = (ForgeChunkGeneratorWrapper) generator;
gen.getHandle().getPopulators().forEach(populator -> populator.populate((World) world, (Chunk) world));
return true;
}
}

View File

@ -1,59 +0,0 @@
package com.dfsek.terra.forge.generation;
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.ForgeUtil;
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", ForgeUtil.createBiomeID(pack, biome.getID()))));
}
}

View File

@ -1,25 +0,0 @@
package com.dfsek.terra.forge.generation;
import com.dfsek.terra.config.pack.ConfigPack;
import net.minecraft.client.gui.screen.BiomeGeneratorTypeScreens;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.DimensionSettings;
import org.jetbrains.annotations.NotNull;
public class TerraGeneratorType extends BiomeGeneratorTypeScreens {
private final ConfigPack pack;
public TerraGeneratorType(ConfigPack pack) {
super(new StringTextComponent("Terra:" + pack.getTemplate().getID()));
this.pack = pack;
}
@Override
protected @NotNull
ChunkGenerator generator(@NotNull Registry<Biome> biomeRegistry, @NotNull Registry<DimensionSettings> chunkGeneratorSettingsRegistry, long seed) {
return new ForgeChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, seed, pack), seed, pack);
}
}

View File

@ -1,35 +0,0 @@
package com.dfsek.terra.forge.handle;
import com.dfsek.terra.api.handle.ItemHandle;
import com.dfsek.terra.api.inventory.Item;
import com.dfsek.terra.api.inventory.item.Enchantment;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.command.arguments.ItemArgument;
import net.minecraft.util.ResourceLocation;
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 (Item) 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 (Enchantment) ForgeRegistries.ENCHANTMENTS.getValue(ResourceLocation.tryParse(id));
}
@Override
public Set<Enchantment> getEnchantments() {
return ForgeRegistries.ENCHANTMENTS.getEntries().stream().map(entry -> (Enchantment) entry.getValue()).collect(Collectors.toSet());
}
}

View File

@ -1,36 +0,0 @@
package com.dfsek.terra.forge.handle;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.handle.WorldHandle;
import com.dfsek.terra.forge.ForgeAdapter;
import com.dfsek.terra.forge.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.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 (EntityType) ForgeRegistries.ENTITIES.getValue(identifier);
}
}

View File

@ -1,81 +0,0 @@
package com.dfsek.terra.forge.listener;
import com.dfsek.terra.api.command.CommandManager;
import com.dfsek.terra.api.command.exception.CommandException;
import com.dfsek.terra.api.platform.CommandSender;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.forge.TerraForgePlugin;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.command.CommandSource;
import net.minecraft.util.text.StringTextComponent;
import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal;
import static com.mojang.brigadier.builder.RequiredArgumentBuilder.argument;
@Mod.EventBusSubscriber(modid = "terra", bus = Mod.EventBusSubscriber.Bus.FORGE)
public class ForgeListener {
private static final TerraForgePlugin INSTANCE = TerraForgePlugin.getInstance();
@SuppressWarnings({"unchecked", "rawtypes"})
@SubscribeEvent
public static void registerCommands(RegisterCommandsEvent event) {
int max = INSTANCE.getManager().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.getManager()));
}
event.getDispatcher().register(literal("terra").executes(context -> 1).then((ArgumentBuilder) assemble(arg, INSTANCE.getManager())));
event.getDispatcher().register(literal("te").executes(context -> 1).then((ArgumentBuilder) assemble(arg, INSTANCE.getManager())));
}
public static RequiredArgumentBuilder<CommandSource, String> assemble(RequiredArgumentBuilder<CommandSource, String> in, CommandManager manager) {
return in.suggests((context, builder) -> {
List<String> args = parseCommand(context.getInput());
CommandSender sender = (CommandSender) context.getSource();
try {
sender = (Entity) context.getSource().getEntityOrException();
} catch(CommandSyntaxException ignore) {
}
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 {
CommandSender sender = (CommandSender) context.getSource();
try {
sender = (Entity) context.getSource().getEntityOrException();
} catch(CommandSyntaxException ignore) {
}
manager.execute(args.remove(0), sender, 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;
}
}

View File

@ -1,15 +0,0 @@
package com.dfsek.terra.forge.listener;
import com.dfsek.terra.forge.TerraForgePlugin;
import net.minecraft.world.gen.feature.Feature;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
public class RegistryListener {
@SubscribeEvent
public static void registerPop(RegistryEvent.Register<Feature<?>> event) {
event.getRegistry().register(TerraForgePlugin.POPULATOR_FEATURE);
}
}

View File

@ -1,64 +0,0 @@
package com.dfsek.terra.forge.mixin;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.forge.TerraForgePlugin;
import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper;
import com.dfsek.terra.forge.generation.TerraBiomeSource;
import com.google.common.base.MoreObjects;
import net.minecraft.util.registry.DynamicRegistries;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.SimpleRegistry;
import net.minecraft.world.Dimension;
import net.minecraft.world.DimensionType;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.DimensionSettings;
import net.minecraft.world.gen.settings.DimensionGeneratorSettings;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Properties;
import java.util.Random;
@Mixin(DimensionGeneratorSettings.class)
public abstract class DimensionGeneratorSettingsMixin {
@Inject(method = "create(Lnet/minecraft/util/registry/DynamicRegistries;Ljava/util/Properties;)Lnet/minecraft/world/gen/settings/DimensionGeneratorSettings;", at = @At("HEAD"), cancellable = true)
private static void fromProperties(DynamicRegistries dynamicRegistries, Properties properties, CallbackInfoReturnable<DimensionGeneratorSettings> cir) {
if(properties.get("level-type") == null) {
return;
}
String prop = properties.get("level-type").toString().trim();
if(prop.startsWith("Terra")) {
String seed = (String) MoreObjects.firstNonNull(properties.get("level-seed"), "");
long l = new Random().nextLong();
if(!seed.isEmpty()) {
try {
long m = Long.parseLong(seed);
if(m != 0L) {
l = m;
}
} catch(NumberFormatException exception) {
l = seed.hashCode();
}
}
String generate_structures = (String) properties.get("generate-structures");
boolean generateStructures = generate_structures == null || Boolean.parseBoolean(generate_structures);
Registry<DimensionType> dimensionTypes = dynamicRegistries.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY);
Registry<Biome> biomes = dynamicRegistries.registryOrThrow(Registry.BIOME_REGISTRY);
Registry<DimensionSettings> chunkGeneratorSettings = dynamicRegistries.registryOrThrow(Registry.NOISE_GENERATOR_SETTINGS_REGISTRY);
SimpleRegistry<Dimension> dimensionOptions = DimensionType.defaultDimensions(dimensionTypes, biomes, chunkGeneratorSettings, l);
prop = prop.substring(prop.indexOf(":") + 1);
ConfigPack pack = TerraForgePlugin.getInstance().getConfigRegistry().get(prop);
if(pack == null) throw new IllegalArgumentException("No such pack " + prop);
TerraForgePlugin.getInstance().logger().info("Using config pack " + pack.getTemplate().getID());
cir.setReturnValue(new DimensionGeneratorSettings(l, generateStructures, false, DimensionGeneratorSettings.withOverworld(dimensionTypes, dimensionOptions, new ForgeChunkGeneratorWrapper(new TerraBiomeSource(biomes, l, pack), l, pack))));
}
}
}

View File

@ -1,37 +0,0 @@
package com.dfsek.terra.forge.mixin;
import com.dfsek.terra.api.util.generic.pair.Pair;
import com.dfsek.terra.forge.TerraForgePlugin;
import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper;
import com.dfsek.terra.world.TerraWorld;
import net.minecraft.world.DimensionType;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerChunkProvider;
import net.minecraft.world.server.ServerWorld;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(ServerWorld.class)
public abstract class ServerWorldMixin {
@Shadow
@Final
private ServerChunkProvider chunkSource;
@Shadow
protected abstract void initCapabilities();
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/server/ServerWorld;initCapabilities()V"))
public void injectConstructor(ServerWorld serverWorld) {
if(chunkSource.getGenerator() instanceof ForgeChunkGeneratorWrapper) {
ForgeChunkGeneratorWrapper chunkGeneratorWrapper = (ForgeChunkGeneratorWrapper) chunkSource.getGenerator();
DimensionType dimensionType = ((World) (Object) this).dimensionType();
TerraForgePlugin.getInstance().getWorldMap().put(dimensionType, Pair.of((ServerWorld) (Object) this, new TerraWorld((com.dfsek.terra.api.world.World) this, chunkGeneratorWrapper.getPack(), TerraForgePlugin.getInstance())));
chunkGeneratorWrapper.setDimensionType(dimensionType);
TerraForgePlugin.getInstance().logger().info("Registered world " + this + " to dimension type " + dimensionType);
}
initCapabilities();
}
}

View File

@ -1,12 +0,0 @@
package com.dfsek.terra.forge.mixin.access;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.spawner.AbstractSpawner;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(AbstractSpawner.class)
public interface AbstractSpawnerAccessor {
@Invoker("getEntityId")
ResourceLocation callGetEntityId();
}

View File

@ -1,21 +0,0 @@
package com.dfsek.terra.forge.mixin.access;
import net.minecraft.client.gui.screen.BiomeGeneratorTypeScreens;
import net.minecraft.util.text.ITextComponent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.List;
@Mixin(BiomeGeneratorTypeScreens.class)
public interface BiomeGeneratorTypeScreensAccessor {
@Accessor("PRESETS")
static List<BiomeGeneratorTypeScreens> getPresets() {
throw new UnsupportedOperationException();
}
@Mutable
@Accessor
void setDescription(ITextComponent description);
}

View File

@ -1,14 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations;
import net.minecraft.world.biome.Biome;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(Biome.class)
@Implements(@Interface(iface = com.dfsek.terra.api.world.Biome.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class BiomeMixin {
public Object terra$getHandle() {
return this;
}
}

View File

@ -1,14 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations;
import net.minecraft.world.gen.ChunkGenerator;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(ChunkGenerator.class)
@Implements(@Interface(iface = com.dfsek.terra.api.world.generator.ChunkGenerator.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ChunkGeneratorMixin {
public Object terra$getHandle() {
return this;
}
}

View File

@ -1,40 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.world.Tree;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.forge.TerraForgePlugin;
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 org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Random;
@Mixin(ConfiguredFeature.class)
@Implements(@Interface(iface = Tree.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ConfiguredFeatureMixin {
@Shadow
public abstract boolean place(ISeedReader p_242765_1_, ChunkGenerator p_242765_2_, Random p_242765_3_, BlockPos p_242765_4_);
@SuppressWarnings({"try"})
public boolean terra$plant(Location l, Random r) {
try(ProfileFrame ignore = TerraForgePlugin.getInstance().getProfiler().profile("forge_tree")) {
ISeedReader world = ((ISeedReader) l.getWorld());
ChunkGenerator generatorWrapper = (ChunkGenerator) l.getWorld().getGenerator();
return place(world, generatorWrapper, r, new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ()));
}
}
public MaterialSet terra$getSpawnable() {
return MaterialSet.get(TerraForgePlugin.getInstance().getWorldHandle().createBlockData("minecraft:grass_block"),
TerraForgePlugin.getInstance().getWorldHandle().createBlockData("minecraft:podzol"),
TerraForgePlugin.getInstance().getWorldHandle().createBlockData("minecraft:mycelium"));
}
}

View File

@ -1,36 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.block;
import com.dfsek.terra.api.block.BlockData;
import com.dfsek.terra.api.block.BlockType;
import com.dfsek.terra.forge.ForgeAdapter;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(Block.class)
@Implements(@Interface(iface = BlockType.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class BlockMixin {
@Shadow
private BlockState defaultBlockState;
public Object terra$getHandle() {
return this;
}
public BlockData terra$getDefaultData() {
return ForgeAdapter.adapt(defaultBlockState);
}
public boolean terra$isSolid() {
return defaultBlockState.canOcclude();
}
@SuppressWarnings("ConstantConditions")
public boolean terra$isWater() {
return ((Object) this) == Blocks.WATER;
}
}

View File

@ -1,63 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.block;
import com.dfsek.terra.api.block.Block;
import com.dfsek.terra.api.block.BlockData;
import com.dfsek.terra.api.block.entity.BlockState;
import com.dfsek.terra.forge.ForgeAdapter;
import com.dfsek.terra.forge.block.ForgeBlock;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import javax.annotation.Nullable;
@Mixin(TileEntity.class)
@Implements(@Interface(iface = BlockState.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class TileEntityMixin {
@Shadow
protected BlockPos worldPosition;
@Shadow
@Nullable
protected World level;
@Shadow
@Nullable
private net.minecraft.block.BlockState blockState;
@Shadow
public abstract boolean hasLevel();
public Object terra$getHandle() {
return this;
}
public Block terra$getBlock() {
return new ForgeBlock(worldPosition, level);
}
public int terra$getX() {
return worldPosition.getX();
}
public int terra$getY() {
return worldPosition.getY();
}
public int terra$getZ() {
return worldPosition.getZ();
}
public BlockData terra$getBlockData() {
return ForgeAdapter.adapt(blockState);
}
public boolean terra$update(boolean applyPhysics) {
if(hasLevel()) level.getChunk(worldPosition).setBlockEntity(worldPosition, (TileEntity) (Object) this);
return true;
}
}

View File

@ -1,21 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.block.state;
import com.dfsek.terra.api.block.entity.Container;
import com.dfsek.terra.api.inventory.Inventory;
import com.dfsek.terra.forge.mixin.implementations.block.TileEntityMixin;
import net.minecraft.tileentity.LockableLootTileEntity;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(LockableLootTileEntity.class)
@Implements(@Interface(iface = Container.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class LockableLootTileEntityMixin extends TileEntityMixin {
public Inventory terra$getInventory() {
return (Inventory) this;
}
public Object terra$getHandle() {
return this;
}
}

View File

@ -1,120 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.block.state;
import com.dfsek.terra.api.block.entity.MobSpawner;
import com.dfsek.terra.api.block.entity.SerialState;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.forge.TerraForgePlugin;
import com.dfsek.terra.forge.mixin.access.AbstractSpawnerAccessor;
import com.dfsek.terra.forge.mixin.implementations.block.TileEntityMixin;
import net.minecraft.tileentity.MobSpawnerTileEntity;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.spawner.AbstractSpawner;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(MobSpawnerTileEntity.class)
@Implements(@Interface(iface = MobSpawner.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class MobSpawnerTileEntityMixin extends TileEntityMixin {
@Shadow
public abstract AbstractSpawner getSpawner();
public EntityType terra$getSpawnedType() {
return (EntityType) Registry.ENTITY_TYPE.get(((AbstractSpawnerAccessor) getSpawner()).callGetEntityId());
}
public void terra$setSpawnedType(@NotNull EntityType creatureType) {
getSpawner().setEntityId((net.minecraft.entity.EntityType<?>) creatureType);
}
public int terra$getDelay() {
return 0;
}
public void terra$setDelay(int delay) {
}
public int terra$getMinSpawnDelay() {
return 0;
}
public void terra$setMinSpawnDelay(int delay) {
}
public int terra$getMaxSpawnDelay() {
return 0;
}
public void terra$setMaxSpawnDelay(int delay) {
}
public int terra$getSpawnCount() {
return 0;
}
public void terra$setSpawnCount(int spawnCount) {
}
public int terra$getMaxNearbyEntities() {
return 0;
}
public void terra$setMaxNearbyEntities(int maxNearbyEntities) {
}
public int terra$getRequiredPlayerRange() {
return 0;
}
public void terra$setRequiredPlayerRange(int requiredPlayerRange) {
}
public int terra$getSpawnRange() {
return 0;
}
public void terra$setSpawnRange(int spawnRange) {
}
public void terra$applyState(String state) {
SerialState.parse(state).forEach((k, v) -> {
switch(k) {
case "type":
terra$setSpawnedType(TerraForgePlugin.getInstance().getWorldHandle().getEntity(v));
return;
case "delay":
terra$setDelay(Integer.parseInt(v));
return;
case "min_delay":
terra$setMinSpawnDelay(Integer.parseInt(v));
return;
case "max_delay":
terra$setMaxSpawnDelay(Integer.parseInt(v));
return;
case "spawn_count":
terra$setSpawnCount(Integer.parseInt(v));
return;
case "spawn_range":
terra$setSpawnRange(Integer.parseInt(v));
return;
case "max_nearby":
terra$setMaxNearbyEntities(Integer.parseInt(v));
return;
case "required_player_range":
terra$setRequiredPlayerRange(Integer.parseInt(v));
return;
default:
throw new IllegalArgumentException("Invalid property: " + k);
}
});
}
}

View File

@ -1,50 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.block.state;
import com.dfsek.terra.api.block.entity.SerialState;
import com.dfsek.terra.api.block.entity.Sign;
import net.minecraft.tileentity.SignTileEntity;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(SignTileEntity.class)
@Implements(@Interface(iface = Sign.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class SignTileEntityMixin {
@Shadow
@Final
private ITextComponent[] messages;
@Shadow
public abstract void setMessage(int p_212365_1_, ITextComponent p_212365_2_);
public @NotNull
String[] terra$getLines() {
String[] lines = new String[messages.length];
for(int i = 0; i < messages.length; i++) {
lines[i] = messages[i].getString();
}
return lines;
}
public @NotNull
String terra$getLine(int index) throws IndexOutOfBoundsException {
return messages[index].getString();
}
public void terra$setLine(int index, @NotNull String line) throws IndexOutOfBoundsException {
setMessage(index, new StringTextComponent(line));
}
public void terra$applyState(String state) {
SerialState.parse(state).forEach((k, v) -> {
if(!k.startsWith("text")) throw new IllegalArgumentException("Invalid property: " + k);
terra$setLine(Integer.parseInt(k.substring(4)), v);
});
}
}

View File

@ -1,55 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.chunk;
import com.dfsek.terra.api.block.Block;
import com.dfsek.terra.api.block.BlockData;
import com.dfsek.terra.api.world.Chunk;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.forge.block.ForgeBlock;
import com.dfsek.terra.forge.block.ForgeBlockData;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.IChunk;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(net.minecraft.world.chunk.Chunk.class)
@Implements(@Interface(iface = Chunk.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ChunkMixin {
@Shadow
@Final
private net.minecraft.world.World level;
public int terra$getX() {
return ((IChunk) this).getPos().x;
}
public int terra$getZ() {
return ((IChunk) this).getPos().z;
}
public World terra$getWorld() {
return (World) level;
}
public Block terra$getBlock(int x, int y, int z) {
BlockPos pos = new BlockPos(x + (terra$getX() << 4), y, z + (terra$getZ() << 4));
return new ForgeBlock(pos, level);
}
public @NotNull
BlockData terra$getBlockData(int x, int y, int z) {
return terra$getBlock(x, y, z).getBlockData();
}
public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) {
((IChunk) this).setBlockState(new BlockPos(x, y, z), ((ForgeBlockData) blockData).getHandle(), false);
}
public Object terra$getHandle() {
return this;
}
}

View File

@ -1,58 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.chunk;
import com.dfsek.terra.api.block.Block;
import com.dfsek.terra.api.block.BlockData;
import com.dfsek.terra.api.world.Chunk;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.forge.block.ForgeBlock;
import com.dfsek.terra.forge.block.ForgeBlockData;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.gen.WorldGenRegion;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(WorldGenRegion.class)
@Implements(@Interface(iface = Chunk.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class WorldGenRegionMixin {
@Final
@Shadow
private int x;
@Final
@Shadow
private int z;
public int terra$getX() {
return x;
}
public int terra$getZ() {
return z;
}
public World terra$getWorld() {
return (World) this;
}
public Block terra$getBlock(int x, int y, int z) {
BlockPos pos = new BlockPos(x + (this.x << 4), y, z + (this.z << 4));
return new ForgeBlock(pos, (WorldGenRegion) (Object) this);
}
public @NotNull
BlockData terra$getBlockData(int x, int y, int z) {
return terra$getBlock(x, y, z).getBlockData();
}
public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) {
((WorldGenRegion) (Object) this).setBlock(new BlockPos(x + (this.x << 4), y, z + (this.z << 4)), ((ForgeBlockData) blockData).getHandle(), 0);
}
public Object terra$getHandle() {
return this;
}
}

View File

@ -1,38 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.chunk.data;
import com.dfsek.terra.api.block.BlockData;
import com.dfsek.terra.api.world.generator.ChunkData;
import com.dfsek.terra.forge.block.ForgeBlockData;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.ChunkPrimer;
import net.minecraft.world.chunk.IChunk;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ChunkPrimer.class)
@Implements(@Interface(iface = ChunkData.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ChunkPrimerMixin {
@Shadow
public abstract BlockState getBlockState(BlockPos pos);
public @NotNull
BlockData terra$getBlockData(int x, int y, int z) {
return new ForgeBlockData(getBlockState(new BlockPos(x, y, z)));
}
public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) {
((IChunk) this).setBlockState(new BlockPos(x, y, z), ((ForgeBlockData) blockData).getHandle(), false);
}
public Object terra$getHandle() {
return this;
}
public int terra$getMaxHeight() {
return 255; // TODO: 1.17 - Implement dynamic height.
}
}

View File

@ -1,25 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.entity;
import com.dfsek.terra.api.platform.CommandSender;
import net.minecraft.command.CommandSource;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(CommandSource.class)
@Implements(@Interface(iface = CommandSender.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class CommandSourceMixin {
@Shadow
public abstract void sendSuccess(ITextComponent p_197030_1_, boolean p_197030_2_);
public void terra$sendMessage(String message) {
sendSuccess(new StringTextComponent(message), true);
}
public Object terra$getHandle() {
return this;
}
}

View File

@ -1,52 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.entity;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.forge.ForgeAdapter;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.UUID;
@Mixin(Entity.class)
@Implements(@Interface(iface = com.dfsek.terra.api.entity.Entity.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class EntityMixin {
@Shadow
public net.minecraft.world.World level;
@Shadow
private BlockPos blockPosition;
@Shadow
public abstract void teleportTo(double destX, double destY, double destZ);
@Shadow
public abstract void sendMessage(ITextComponent p_145747_1_, UUID p_145747_2_);
public Object terra$getHandle() {
return this;
}
public Location terra$getLocation() {
return new Location((World) level, ForgeAdapter.adapt(blockPosition));
}
public void terra$setLocation(Location location) {
teleportTo(location.getX(), location.getY(), location.getZ());
}
public World terra$getWorld() {
return (World) level;
}
public void terra$sendMessage(String message) {
sendMessage(new StringTextComponent(message), UUID.randomUUID()); // TODO: look into how this actually works and make it less jank
}
}

View File

@ -1,14 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.entity;
import net.minecraft.entity.EntityType;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(EntityType.class)
@Implements(@Interface(iface = com.dfsek.terra.api.entity.EntityType.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class EntityTypeMixin {
public Object terra$getHandle() {
return this;
}
}

View File

@ -1,13 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.entity;
import com.dfsek.terra.api.entity.Player;
import net.minecraft.entity.player.PlayerEntity;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(PlayerEntity.class)
@Implements(@Interface(iface = Player.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class PlayerEntityMixin extends EntityMixin {
}

View File

@ -1,32 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.inventory;
import com.dfsek.terra.api.inventory.Inventory;
import com.dfsek.terra.api.inventory.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.tileentity.LockableTileEntity;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(LockableTileEntity.class)
@Implements(@Interface(iface = Inventory.class, prefix = "terra$", remap = Interface.Remap.NONE))
public class LockableTileEntityMixin {
public Object terra$getHandle() {
return this;
}
public int terra$getSize() {
return ((LockableTileEntity) (Object) this).getContainerSize();
}
@SuppressWarnings("ConstantConditions")
public ItemStack terra$getItem(int slot) {
net.minecraft.item.ItemStack itemStack = ((LockableTileEntity) (Object) this).getItem(slot);
return itemStack.getItem() == Items.AIR ? null : (ItemStack) (Object) itemStack;
}
@SuppressWarnings("ConstantConditions")
public void terra$setItem(int slot, ItemStack newStack) {
((LockableTileEntity) (Object) this).setItem(slot, (net.minecraft.item.ItemStack) (Object) newStack);
}
}

View File

@ -1,28 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.inventory.item;
import com.dfsek.terra.api.inventory.ItemStack;
import net.minecraft.item.Item;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(Item.class)
@Implements(@Interface(iface = com.dfsek.terra.api.inventory.Item.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ItemMixin {
@Shadow
public abstract int getMaxDamage();
public Object terra$getHandle() {
return this;
}
@SuppressWarnings("ConstantConditions")
public ItemStack terra$newItemStack(int amount) {
return (ItemStack) (Object) new net.minecraft.item.ItemStack((Item) (Object) this, amount);
}
public double terra$getMaxDurability() {
return getMaxDamage();
}
}

View File

@ -1,62 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.inventory.item;
import com.dfsek.terra.api.inventory.Item;
import com.dfsek.terra.api.inventory.item.ItemMeta;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Intrinsic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ItemStack.class)
@Implements(@Interface(iface = com.dfsek.terra.api.inventory.ItemStack.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ItemStackMixin {
@Shadow
public abstract int getCount();
@Shadow
public abstract void setCount(int count);
@Shadow
public abstract net.minecraft.item.Item getItem();
@Shadow
public abstract boolean isDamageableItem();
@Shadow
public abstract void setTag(@Nullable CompoundNBT p_77982_1_);
public int terra$getAmount() {
return getCount();
}
public void terra$setAmount(int i) {
setCount(i);
}
public Item terra$getType() {
return (Item) getItem();
}
public ItemMeta terra$getItemMeta() {
return (ItemMeta) this;
}
@SuppressWarnings("ConstantConditions")
public void terra$setItemMeta(ItemMeta meta) {
setTag(((ItemStack) (Object) meta).getTag());
}
public Object terra$getHandle() {
return this;
}
@Intrinsic
public boolean terra$isDamageable() {
return isDamageableItem();
}
}

View File

@ -1,39 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.inventory.meta;
import com.dfsek.terra.api.inventory.ItemStack;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.util.registry.Registry;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Objects;
@Mixin(Enchantment.class)
@Implements(@Interface(iface = com.dfsek.terra.api.inventory.item.Enchantment.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class EnchantmentMixin {
@Shadow
public abstract boolean isCompatibleWith(Enchantment p_191560_1_);
@Shadow
public abstract boolean canEnchant(net.minecraft.item.ItemStack p_92089_1_);
public Object terra$getHandle() {
return this;
}
@SuppressWarnings("ConstantConditions")
public boolean terra$canEnchantItem(ItemStack itemStack) {
return canEnchant((net.minecraft.item.ItemStack) (Object) itemStack);
}
public String terra$getID() {
return Objects.requireNonNull(Registry.ENCHANTMENT.getId((Enchantment) (Object) this)).toString();
}
public boolean terra$conflictsWith(com.dfsek.terra.api.inventory.item.Enchantment other) {
return !isCompatibleWith((Enchantment) other);
}
}

View File

@ -1,36 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.inventory.meta;
import com.dfsek.terra.api.inventory.item.Damageable;
import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Intrinsic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ItemStack.class)
@Implements(@Interface(iface = Damageable.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ItemStackDamageableMixin {
@Shadow
public abstract boolean isDamaged();
@Shadow
public abstract int getDamageValue();
@Shadow
public abstract void setDamageValue(int p_196085_1_);
public boolean terra$hasDamage() {
return isDamaged();
}
@Intrinsic
public void terra$setDamage(int damage) {
setDamageValue(damage);
}
@Intrinsic
public int terra$getDamage() {
return getDamageValue();
}
}

View File

@ -1,50 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.inventory.meta;
import com.dfsek.terra.api.inventory.item.Enchantment;
import com.dfsek.terra.api.inventory.item.ItemMeta;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.util.registry.Registry;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Intrinsic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@Mixin(ItemStack.class)
@Implements(@Interface(iface = ItemMeta.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ItemStackMetaMixin {
@Shadow
public abstract ListNBT getEnchantmentTags();
@Shadow
public abstract boolean isEnchanted();
@Shadow
public abstract void enchant(net.minecraft.enchantment.Enchantment p_77966_1_, int p_77966_2_);
public Object terra$getHandle() {
return this;
}
@Intrinsic(displace = true)
public Map<Enchantment, Integer> terra$getEnchantments() {
if(!isEnchanted()) return Collections.emptyMap();
Map<Enchantment, Integer> map = new HashMap<>();
getEnchantmentTags().forEach(enchantment -> {
CompoundNBT eTag = (CompoundNBT) enchantment;
map.put((Enchantment) Registry.ENCHANTMENT.byId(eTag.getInt("id")), eTag.getInt("lvl"));
});
return map;
}
public void terra$addEnchantment(Enchantment enchantment, int level) {
enchant((net.minecraft.enchantment.Enchantment) enchantment, level);
}
}

View File

@ -1,5 +0,0 @@
/**
* Mixins in this package implement Terra
* interfaces in Minecraft classes.
*/
package com.dfsek.terra.forge.mixin.implementations;

View File

@ -1,86 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.world;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.block.Block;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.world.Chunk;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.generator.ChunkGenerator;
import com.dfsek.terra.api.world.generator.GeneratorWrapper;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.forge.block.ForgeBlock;
import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IServerWorld;
import net.minecraft.world.server.ServerWorld;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Intrinsic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ServerWorld.class)
@Implements(@Interface(iface = World.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ServerWorldMixin {
@Shadow
public abstract long getSeed();
public int terra$getMaxHeight() {
return ((ServerWorld) (Object) this).getMaxBuildHeight();
}
public ChunkGenerator terra$getGenerator() {
return (ChunkGenerator) ((ServerWorld) (Object) this).getChunkSource().getGenerator();
}
public Chunk terra$getChunkAt(int x, int z) {
return (Chunk) ((ServerWorld) (Object) this).getChunk(x, z);
}
public Block terra$getBlockAt(int x, int y, int z) {
return new ForgeBlock(new BlockPos(x, y, z), ((ServerWorld) (Object) this));
}
public Entity terra$spawnEntity(Location location, EntityType entityType) {
net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType<?>) entityType).create(((ServerWorld) (Object) this));
entity.setPos(location.getX(), location.getY(), location.getZ());
((ServerWorld) (Object) this).addFreshEntity(entity);
return (Entity) entity;
}
@Intrinsic
public long terra$getSeed() {
return getSeed();
}
public int terra$getMinHeight() {
return 0;
}
public Object terra$getHandle() {
return this;
}
public boolean terra$isTerraWorld() {
return terra$getGenerator() instanceof GeneratorWrapper;
}
public TerraChunkGenerator terra$getTerraGenerator() {
return ((ForgeChunkGeneratorWrapper) terra$getGenerator()).getHandle();
}
/**
* Overridden in the same manner as {@link WorldGenRegionMixin#hashCode()}
*
* @param other Another object
* @return Whether this world is the same as other.
* @see WorldGenRegionMixin#hashCode()
*/
@SuppressWarnings("ConstantConditions")
@Override
public boolean equals(Object other) {
if(!(other instanceof IServerWorld)) return false;
return (IServerWorld) this == (((IServerWorld) other).getLevel());
}
}

View File

@ -1,108 +0,0 @@
package com.dfsek.terra.forge.mixin.implementations.world;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.block.Block;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.world.Chunk;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.generator.ChunkGenerator;
import com.dfsek.terra.api.world.generator.GeneratorWrapper;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.forge.block.ForgeBlock;
import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.gen.WorldGenRegion;
import net.minecraft.world.server.ServerWorld;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Intrinsic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(WorldGenRegion.class)
@Implements(@Interface(iface = World.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class WorldGenRegionMixin {
@Shadow
@Final
private ServerWorld level;
@Shadow
@Final
private long seed;
public int terra$getMaxHeight() {
return ((WorldGenRegion) (Object) this).getMaxBuildHeight();
}
@SuppressWarnings("deprecation")
public ChunkGenerator terra$getGenerator() {
return (ChunkGenerator) ((WorldGenRegion) (Object) this).getLevel().getChunkSource().getGenerator();
}
public Chunk terra$getChunkAt(int x, int z) {
return (Chunk) ((WorldGenRegion) (Object) this).getChunk(x, z);
}
public Block terra$getBlockAt(int x, int y, int z) {
return new ForgeBlock(new BlockPos(x, y, z), ((WorldGenRegion) (Object) this));
}
@SuppressWarnings("deprecation")
public Entity terra$spawnEntity(Location location, EntityType entityType) {
net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType<?>) entityType).create(((WorldGenRegion) (Object) this).getLevel());
entity.setPos(location.getX(), location.getY(), location.getZ());
((WorldGenRegion) (Object) this).addFreshEntity(entity);
return (Entity) entity;
}
@Intrinsic
public long terra$getSeed() {
return seed;
}
public int terra$getMinHeight() {
return 0;
}
public Object terra$getHandle() {
return this;
}
public boolean terra$isTerraWorld() {
return terra$getGenerator() instanceof GeneratorWrapper;
}
public TerraChunkGenerator terra$getTerraGenerator() {
return ((ForgeChunkGeneratorWrapper) terra$getGenerator()).getHandle();
}
/**
* We need regions delegating to the same world
* to have the same hashcode. This
* minimizes cache misses.
* <p>
* This is sort of jank, but shouldn't(tm)
* break any other mods, unless they're doing
* something they really shouldn't, since
* ChunkRegions are not supposed to persist.
*/
@Override
public int hashCode() {
return level.hashCode();
}
/**
* Overridden in the same manner as {@link #hashCode()}
*
* @param other Another object
* @return Whether this world is the same as other.
* @see #hashCode()
*/
@Override
public boolean equals(Object other) {
if(!(other instanceof WorldGenRegion)) return false;
return level.equals(((WorldGenRegion) other).getLevel());
}
}

View File

@ -1,29 +0,0 @@
package com.dfsek.terra.forge.mixin.init;
import com.dfsek.terra.forge.TerraForgePlugin;
import com.dfsek.terra.forge.generation.TerraGeneratorType;
import com.dfsek.terra.forge.mixin.access.BiomeGeneratorTypeScreensAccessor;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.BiomeGeneratorTypeScreens;
import net.minecraft.resources.ResourcePackList;
import net.minecraft.util.text.StringTextComponent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(Minecraft.class)
public abstract class MinecraftClientMixin {
@Redirect(method = "<init>", at = @At(value = "INVOKE",
target = "Lnet/minecraft/resources/ResourcePackList;reload()V" // sorta arbitrary position, after mod init, before window opens
))
public void injectConstructor(ResourcePackList resourcePackList) {
TerraForgePlugin.getInstance().init(); // Load during MinecraftClient construction, after other mods have registered blocks and stuff
TerraForgePlugin.getInstance().getConfigRegistry().forEach(pack -> {
final BiomeGeneratorTypeScreens generatorType = new TerraGeneratorType(pack);
//noinspection ConstantConditions
((BiomeGeneratorTypeScreensAccessor) generatorType).setDescription(new StringTextComponent("Terra:" + pack.getTemplate().getID()));
BiomeGeneratorTypeScreensAccessor.getPresets().add(1, generatorType);
});
resourcePackList.reload();
}
}

View File

@ -1,16 +0,0 @@
package com.dfsek.terra.forge.mixin.init;
import com.dfsek.terra.forge.TerraForgePlugin;
import net.minecraft.server.Main;
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.CallbackInfo;
@Mixin(Main.class)
public class MinecraftServerMixin {
@Inject(method = "main([Ljava/lang/String;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/registry/DynamicRegistries;builtin()Lnet/minecraft/util/registry/DynamicRegistries$Impl;"))
private static void injectConstructor(String[] args, CallbackInfo ci) {
TerraForgePlugin.getInstance().init(); // Load during MinecraftServer construction, after other mods have registered blocks and stuff
}
}

View File

@ -1,17 +0,0 @@
modLoader = "javafml"
loaderVersion = "[36,)"
license = "@LICENSE@"
issueTrackerURL = "@ISSUES@"
[[mods]]
modId = "terra"
version = "@VERSION@"
displayName = "Terra"
displayURL = "@WIKI@"
authors = "dfsek & Terra contributors"
description = "@DESCRIPTION@"
[[dependencies.terra]]
modId = "forge"
mandatory = true
versionRange = "[36,)"
ordering = "NONE"
side = "BOTH"

View File

@ -1,6 +0,0 @@
{
"pack": {
"description": "Terra Resources",
"pack_format": 6
}
}

View File

@ -1,45 +0,0 @@
{
"required": true,
"package": "com.dfsek.terra.forge.mixin",
"compatibilityLevel": "JAVA_8",
"refmap": "terra-refmap.json",
"mixins": [
"DimensionGeneratorSettingsMixin",
"ServerWorldMixin",
"access.AbstractSpawnerAccessor",
"access.BiomeGeneratorTypeScreensAccessor",
"implementations.BiomeMixin",
"implementations.ChunkGeneratorMixin",
"implementations.ConfiguredFeatureMixin",
"implementations.block.BlockMixin",
"implementations.block.TileEntityMixin",
"implementations.block.state.LockableLootTileEntityMixin",
"implementations.block.state.MobSpawnerTileEntityMixin",
"implementations.block.state.SignTileEntityMixin",
"implementations.chunk.ChunkMixin",
"implementations.chunk.WorldGenRegionMixin",
"implementations.chunk.data.ChunkPrimerMixin",
"implementations.entity.CommandSourceMixin",
"implementations.entity.EntityMixin",
"implementations.entity.EntityTypeMixin",
"implementations.entity.PlayerEntityMixin",
"implementations.inventory.LockableTileEntityMixin",
"implementations.inventory.item.ItemMixin",
"implementations.inventory.item.ItemStackMixin",
"implementations.inventory.meta.EnchantmentMixin",
"implementations.inventory.meta.ItemStackDamageableMixin",
"implementations.inventory.meta.ItemStackMetaMixin",
"implementations.world.ServerWorldMixin",
"implementations.world.WorldGenRegionMixin"
],
"client": [
"init.MinecraftClientMixin"
],
"server": [
"init.MinecraftServerMixin"
],
"injectors": {
"defaultRequire": 1
},
"minVersion": "0.8"
}

View File

@ -1,20 +0,0 @@
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"

View File

@ -1,6 +0,0 @@
{
"pack": {
"description": "Terra resources",
"pack_format": 6
}
}