diff --git a/libraries/biomes/README.md b/libraries/biomes/README.md
new file mode 100644
index 00000000..8fa49f5f
--- /dev/null
+++ b/libraries/biomes/README.md
@@ -0,0 +1,41 @@
+# Biomes API
+
+The Biomes API provides events and utilities for registering and working with biomes.
+
+## Registering Custom Biomes
+
+Biome registration should be done in a listener to the `REGISTER_BIOMES` event. The `BiomeRegistry` class provides utility methods for registering biomes.
+
+An example is shown below.
+
+```java
+package com.example;
+
+import net.ornithemc.osl.biomes.api.BiomeEvents;
+import net.ornithemc.osl.entrypoints.api.ModInitializer;
+
+public class ExampleInitializer implements ModInitializer {
+
+ @Override
+ public void init() {
+ BiomeEvents.REGISTER_BIOMES.register(ExampleBiomes::init);
+ }
+}
+```
+
+```java
+package com.example;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.api.BiomeRegistry;
+import net.ornithemc.osl.core.util.NamespacedIdentifiers;
+
+public final class ExampleBiomes {
+
+ public static final CookieBiome COOKIE = BiomeRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new CookieBiome(new Biome.Settings().setName("Cookie")));
+
+ public static void init() {
+ }
+}
+```
diff --git a/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/build.gradle b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/build.gradle
new file mode 100644
index 00000000..0a350fdb
--- /dev/null
+++ b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/build.gradle
@@ -0,0 +1 @@
+setUpModule(project)
diff --git a/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/gradle.properties b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/gradle.properties
new file mode 100644
index 00000000..03ed48f0
--- /dev/null
+++ b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/gradle.properties
@@ -0,0 +1,4 @@
+min_mc_version = 1.8.2-pre5
+max_mc_version = 15w51b
+
+minecraft_version = 1.8.9
diff --git a/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java
new file mode 100644
index 00000000..0d49c6f2
--- /dev/null
+++ b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java
@@ -0,0 +1,34 @@
+package net.ornithemc.osl.biomes.api;
+
+import net.ornithemc.osl.core.api.events.Event;
+
+/**
+ * Events related to the biomes lifecycle.
+ */
+public final class BiomeEvents {
+
+ /**
+ * This event is invoked upon game start-up, after Vanilla biome registration is finished.
+ *
+ *
+ * Custom biome registration should be done in a listener of this event.
+ * Helper methods for registering biomes can be found in the {@linkplain
+ * BiomeRegistry} class.
+ *
+ *
+ * Listeners to this event should be registered in your mod's entrypoint,
+ * and can be done as follows:
+ *
+ *
+ * {@code
+ * BiomeEvents.REGISTER_BIOMES.register(() -> {
+ * BiomeRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new CookieBiome());
+ * });
+ * }
+ *
+ *
+ * @see BiomeRegistry
+ */
+ public static final Event REGISTER_BIOMES = Event.runnable();
+
+}
diff --git a/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java
new file mode 100644
index 00000000..86e85031
--- /dev/null
+++ b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java
@@ -0,0 +1,106 @@
+package net.ornithemc.osl.biomes.api;
+
+import java.util.Set;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.registries.api.registry.ResourceKey;
+
+/**
+ * Public access to the Biomes registry.
+ */
+public final class BiomeRegistry {
+
+ /**
+ * @return the numerical ID assigned to the given biome.
+ */
+ public static int getId(Biome biome) {
+ return BiomeRegistryImpl.getId(biome);
+ }
+
+ /**
+ * @return the namespaced ID assigned to the given biome.
+ */
+ public static NamespacedIdentifier getIdentifier(Biome biome) {
+ return BiomeRegistryImpl.getIdentifier(biome);
+ }
+
+ /**
+ * @return the resource key assigned to the given biome.
+ */
+ public static ResourceKey getKey(Biome biome) {
+ return BiomeRegistryImpl.getKey(biome);
+ }
+
+ /**
+ * @return the biome mapped to the given numerical ID.
+ */
+ public static Biome getBiome(int id) {
+ return BiomeRegistryImpl.getBiome(id);
+ }
+
+ /**
+ * @return the biome mapped to the given namespaced ID.
+ */
+ public static Biome getBiome(NamespacedIdentifier identifier) {
+ return BiomeRegistryImpl.getBiome(identifier);
+ }
+
+ /**
+ * @return the biome mapped to the given resource key.
+ */
+ public static Biome getBiome(ResourceKey key) {
+ return BiomeRegistryImpl.getBiome(key);
+ }
+
+ /**
+ * @return a set containing all namespaced IDs in the registry.
+ */
+ public static Set identifierSet() {
+ return BiomeRegistryImpl.identifierSet();
+ }
+
+ /**
+ * @return a set containing all resource keys in the registry.
+ */
+ public static Set> keySet() {
+ return BiomeRegistryImpl.keySet();
+ }
+
+ /**
+ * @param the biome type.
+ * @param identifier the namespaced ID of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ */
+ public static T register(NamespacedIdentifier identifier, T biome) {
+ return BiomeRegistryImpl.register(identifier, biome);
+ }
+
+ /**
+ * @param the biome type.
+ * @param key the resource key of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ */
+ public static T register(ResourceKey key, T biome) {
+ return BiomeRegistryImpl.register(key, biome);
+ }
+
+ /**
+ * @param the biome type.
+ * @param id the numerical ID of the biome.
+ * @param key the namespaced ID of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ *
+ * @deprecated use {@linkplain #register(NamespacedIdentifier, Biome)}
+ * or {@linkplain #register(ResourceKey, Biome)} instead.
+ */
+ @Deprecated
+ public static T register(int id, NamespacedIdentifier key, T biome) {
+ return BiomeRegistryImpl.register(id, key, biome);
+ }
+}
diff --git a/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java
new file mode 100644
index 00000000..06d6a59b
--- /dev/null
+++ b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java
@@ -0,0 +1,13 @@
+package net.ornithemc.osl.biomes.api.biome;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.registries.api.registry.Registry;
+
+public interface BiomeExtension {
+
+ Registry REGISTRY = BiomeRegistryImpl.REGISTRY;
+ int AUTO_ASSIGN_ID = -172;
+
+}
diff --git a/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java
new file mode 100644
index 00000000..46583dba
--- /dev/null
+++ b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java
@@ -0,0 +1,111 @@
+package net.ornithemc.osl.biomes.impl;
+
+import java.util.Set;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
+import net.ornithemc.osl.biomes.api.BiomeEvents;
+import net.ornithemc.osl.biomes.impl.biome.BiomeIdFixer;
+import net.ornithemc.osl.registries.api.registry.Registries;
+import net.ornithemc.osl.registries.api.registry.Registry;
+import net.ornithemc.osl.registries.api.registry.RegistryKeys;
+import net.ornithemc.osl.registries.api.registry.ResourceKey;
+import net.ornithemc.osl.registries.api.registry.SyncedRegistries;
+import net.ornithemc.osl.registries.impl.registry.RegistriesImpl;
+
+public final class BiomeRegistryImpl {
+
+ public static final Registry REGISTRY = Registries.registerSimple(RegistryKeys.BIOME, () -> Biome.BY_ID.getClass());
+
+ private static boolean locked = true;
+
+ public static int getId(Biome biome) {
+ return REGISTRY.getId(biome);
+ }
+
+ public static NamespacedIdentifier getIdentifier(Biome biome) {
+ return REGISTRY.getIdentifier(biome);
+ }
+
+ public static ResourceKey getKey(Biome biome) {
+ return REGISTRY.getKey(biome);
+ }
+
+ public static Biome getBiome(int id) {
+ return REGISTRY.get(id);
+ }
+
+ public static Biome getBiome(NamespacedIdentifier identifier) {
+ return REGISTRY.get(identifier);
+ }
+
+ public static Biome getBiome(ResourceKey key) {
+ return REGISTRY.get(key);
+ }
+
+ public static Set identifierSet() {
+ return REGISTRY.identifierSet();
+ }
+
+ public static Set> keySet() {
+ return REGISTRY.keySet();
+ }
+
+ @SuppressWarnings("deprecation")
+ public static T register(NamespacedIdentifier identifier, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ return Registry.register(REGISTRY, biome.id, identifier, biome);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public static T register(ResourceKey key, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ return Registry.register(REGISTRY, biome.id, key, biome);
+ }
+ }
+
+ @Deprecated
+ public static T register(int id, NamespacedIdentifier key, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ if (biome.id != id) {
+ throw new IllegalArgumentException("ID " + id + " does not match biome ID " + biome.id + " for " + key);
+ }
+
+ return Registry.register(REGISTRY, id, key, biome);
+ }
+ }
+
+ public static void init() {
+ SyncedRegistries.register(RegistryKeys.BIOME);
+ SyncedRegistries.registerFixer(RegistryKeys.BIOME, NamespacedIdentifiers.from("biome/id"), new BiomeIdFixer());
+ }
+
+ public static void unlock() {
+ locked = false;
+ }
+
+ public static void registerBiomes() {
+ VanillaBiomes.init();
+ BiomeEvents.REGISTER_BIOMES.invoker().run();
+ }
+
+ public static void registerUnknownBiomes() {
+ for (Biome biome : Biome.BY_ID) {
+ if (biome != null && REGISTRY.getIdentifier(biome) == null) {
+ NamespacedIdentifier identifier = NamespacedIdentifiers.from("osl", "biome_" + biome.id);
+
+ RegistriesImpl.LOGGER.warn("Biome {}/{}", biome.id, biome.getClass().getSimpleName() + " was not registered to OSL's Biome registry! Adding it as '" + identifier + "'...");
+ BiomeRegistryImpl.register(identifier, biome);
+ }
+ }
+ }
+}
diff --git a/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/BiomesMixinPlugin.java b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/BiomesMixinPlugin.java
new file mode 100644
index 00000000..e52a2ca8
--- /dev/null
+++ b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/BiomesMixinPlugin.java
@@ -0,0 +1,45 @@
+package net.ornithemc.osl.biomes.impl;
+
+import java.util.List;
+import java.util.Set;
+
+import org.objectweb.asm.tree.ClassNode;
+
+import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
+import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
+
+public class BiomesMixinPlugin implements IMixinConfigPlugin {
+
+ public static final boolean BIOME_IDS_BEYOND_255_SUPPORTED = false;
+
+ @Override
+ public void onLoad(String mixinPackage) {
+ }
+
+ @Override
+ public String getRefMapperConfig() {
+ return null;
+ }
+
+ @Override
+ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
+ return true;
+ }
+
+ @Override
+ public void acceptTargets(Set myTargets, Set otherTargets) {
+ }
+
+ @Override
+ public List getMixins() {
+ return null;
+ }
+
+ @Override
+ public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
+ }
+
+ @Override
+ public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
+ }
+}
diff --git a/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/VanillaBiomes.java b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/VanillaBiomes.java
new file mode 100644
index 00000000..a17199dd
--- /dev/null
+++ b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/VanillaBiomes.java
@@ -0,0 +1,146 @@
+package net.ornithemc.osl.biomes.impl;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
+
+public final class VanillaBiomes {
+
+ /**
+ * Namespaced IDs were introduced in 1.9. Before then, the numerical IDs
+ * were the only unique identifiers for biomes. Here we assign namespaced
+ * IDs to pre-1.9 biomes, matching the 1.9 IDs where possible.
+ */
+ private static final String[] IDENTIFIERS = {
+ // grouped per 10 for easier lookup
+
+ "ocean",
+ "plains",
+ "desert",
+ "extreme_hills",
+ "forest",
+ "taiga",
+ "swampland",
+ "river",
+ "hell",
+ "sky",
+
+ "frozen_ocean",
+ "frozen_river",
+ "ice_flats",
+ "ice_mountains",
+ "mushroom_island",
+ "mushroom_island_shore",
+ "beaches",
+ "desert_hills",
+ "forest_hills",
+ "taiga_hills",
+
+ "smaller_extreme_hills",
+ "jungle",
+ "jungle_hills",
+ "jungle_edge",
+ "deep_ocean",
+ "stone_beach",
+ "cold_beach",
+ "birch_forest",
+ "birch_forest_hills",
+ "roofed_forest",
+
+ "taiga_cold",
+ "taiga_cold_hills",
+ "redwood_taiga",
+ "redwood_taiga_hills",
+ "extreme_hills_with_trees",
+ "savanna",
+ "savanna_rock",
+ "mesa",
+ "mesa_rock",
+ "mesa_clear_rock"
+ };
+ private static final String[] MUTATED_IDENTIFIERS = {
+ null,
+ "mutated_plains",
+ "mutated_desert",
+ "mutated_extreme_hills",
+ "mutated_forest",
+ "mutated_taiga",
+ "mutated_swampland",
+ null,
+ null,
+ null,
+
+ null,
+ null,
+ "mutated_ice_flats",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+
+ null,
+ "mutated_jungle",
+ null,
+ "mutated_jungle_edge",
+ null,
+ null,
+ null,
+ "mutated_birch_forest",
+ "mutated_birch_forest_hills",
+ "mutated_roofed_forest",
+
+ "mutated_taiga_cold",
+ null,
+ "mutated_redwood_taiga",
+ "mutated_redwood_taiga_hills",
+ "mutated_extreme_hills_with_trees",
+ "mutated_savanna",
+ "mutated_savanna_rock",
+ "mutated_mesa",
+ "mutated_mesa_rock",
+ "mutated_mesa_clear_rock"
+ };
+
+ public static final int MAX_ID = 255;
+ public static final int MUTATED_ID_OFFSET = 128;
+
+ static void init() {
+ for (Field f : Biome.class.getDeclaredFields()) {
+ if (Modifier.isStatic(f.getModifiers()) && Biome.class.isAssignableFrom(f.getType())) {
+ try {
+ Biome biome = (Biome) f.get(null);
+
+ if (biome != null) {
+ register(biome);
+ }
+ } catch (Throwable t) {
+ }
+ }
+ }
+ }
+
+ private static void register(Biome biome) {
+ if (biome.id >= 0 && biome.id < IDENTIFIERS.length) {
+ String identifier = IDENTIFIERS[biome.id];
+
+ if (identifier != null) {
+ BiomeRegistryImpl.register(NamespacedIdentifiers.from(identifier), biome);
+ }
+ }
+
+ if (biome.id >= 0 && biome.id < MUTATED_IDENTIFIERS.length) {
+ Biome mutated = Biome.BY_ID[biome.id + MUTATED_ID_OFFSET];
+ String identifier = MUTATED_IDENTIFIERS[biome.id];
+
+ if (identifier != null) {
+ BiomeRegistryImpl.register(NamespacedIdentifiers.from(identifier), mutated);
+ }
+ }
+ }
+}
diff --git a/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java
new file mode 100644
index 00000000..1b77c6af
--- /dev/null
+++ b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java
@@ -0,0 +1,6 @@
+package net.ornithemc.osl.biomes.impl.biome;
+
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+
+public interface BiomeExtensionImpl extends BiomeExtension {
+}
diff --git a/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeIdFixer.java b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeIdFixer.java
new file mode 100644
index 00000000..1bacf15f
--- /dev/null
+++ b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeIdFixer.java
@@ -0,0 +1,19 @@
+package net.ornithemc.osl.biomes.impl.biome;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.registries.api.registry.sync.IdFixer;
+
+public class BiomeIdFixer implements IdFixer {
+
+ @Override
+ public void apply() {
+ for (int id = 0; id < Biome.BY_ID.length; id++) {
+ Biome biome = Biome.BY_ID[id];
+
+ if (biome != null) {
+ biome.id = id;
+ }
+ }
+ }
+}
diff --git a/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java
new file mode 100644
index 00000000..60bbefe9
--- /dev/null
+++ b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java
@@ -0,0 +1,132 @@
+package net.ornithemc.osl.biomes.impl.mixin.common;
+
+import org.objectweb.asm.Opcodes;
+
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Mutable;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.At.Shift;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.ModifyVariable;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
+import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.biomes.impl.BiomesMixinPlugin;
+import net.ornithemc.osl.biomes.impl.VanillaBiomes;
+import net.ornithemc.osl.registries.api.registry.RegistryKeys;
+import net.ornithemc.osl.registries.api.registry.SyncedRegistries;
+import net.ornithemc.osl.registries.api.registry.sync.ArrayMapper;
+import net.ornithemc.osl.registries.api.registry.sync.DynamicArray;
+
+@Mixin(Biome.class)
+public class BiomeMixin implements BiomeExtension {
+
+ @Shadow @Final @Mutable
+ private static Biome[] BY_ID;
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "HEAD"
+ )
+ )
+ private static void osl$biomes$unlockBiomeRegistry(CallbackInfo ci) {
+ BiomeRegistryImpl.unlock();
+ }
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "FIELD",
+ target = "Lnet/minecraft/world/biome/Biome;BY_ID:[Lnet/minecraft/world/biome/Biome;",
+ opcode = Opcodes.GETSTATIC,
+ ordinal = 0
+ )
+ )
+ private static void osl$biomes$registerBiomes(CallbackInfo ci) {
+ BiomeRegistryImpl.registerBiomes();
+ BiomeRegistryImpl.registerUnknownBiomes();
+ }
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "TAIL"
+ )
+ )
+ private static void osl$biomes$registerArrayMappers(CallbackInfo ci) {
+ SyncedRegistries.registerMapper(RegistryKeys.BIOME, NamespacedIdentifiers.from("biome/by_id"), ArrayMapper.of(() -> BY_ID, a -> BY_ID = a));
+ }
+
+ @ModifyVariable(
+ method = "",
+ argsOnly = true,
+ ordinal = 0,
+ at = @At(
+ value = "INVOKE",
+ target = "Ljava/lang/Object;()V",
+ shift = Shift.AFTER
+ )
+ )
+ private int osl$biomes$handleAutoAssignId(int id) {
+ if (id == AUTO_ASSIGN_ID) {
+ // the Biome[] array must contain all biomes so this should
+ // give us a valid ID for the Biome registry to use.
+ id = DynamicArray.length(BY_ID);
+
+ // keep 0-255 free for all Vanilla biomes
+ if (BiomesMixinPlugin.BIOME_IDS_BEYOND_255_SUPPORTED && id <= VanillaBiomes.MAX_ID) {
+ id = VanillaBiomes.MAX_ID + 1;
+ }
+ }
+
+ if (!BiomesMixinPlugin.BIOME_IDS_BEYOND_255_SUPPORTED && id > VanillaBiomes.MAX_ID) {
+ throw new IllegalStateException("Biome IDs above 255 are not supported at this time!"
+ + " Biome IDs should be limited to the range 0-255"
+ + " unless the save format has been modified to support IDs beyond 255.");
+ }
+
+ return id;
+ }
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "FIELD",
+ target = "Lnet/minecraft/world/biome/Biome;BY_ID:[Lnet/minecraft/world/biome/Biome;",
+ opcode = Opcodes.GETSTATIC,
+ args = "array=set"
+ )
+ )
+ private void osl$biomes$growArrays(int id, CallbackInfo ci) {
+ int capacity = id + 1;
+
+ BY_ID = DynamicArray.grow(BY_ID, capacity);
+ }
+
+ @WrapOperation(
+ method = "mutate()Lnet/minecraft/world/biome/Biome;",
+ at = @At(
+ value = "INVOKE",
+ target = "Lnet/minecraft/world/biome/Biome;mutate(I)Lnet/minecraft/world/biome/Biome;"
+ )
+ )
+ private static Biome osl$biomes$handleAutoAssignIdForMutatedBiomes(Biome original, int id, Operation op) {
+ if (BiomesMixinPlugin.BIOME_IDS_BEYOND_255_SUPPORTED && original.id > VanillaBiomes.MAX_ID) {
+ // the Biome[] array must contain all biomes so this should
+ // give us a valid ID for the Biome registry to use.
+ id = DynamicArray.length(BY_ID);
+ }
+
+ return op.call(original, id);
+ }
+}
diff --git a/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/resources/fabric.mod.json b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/resources/fabric.mod.json
new file mode 100644
index 00000000..9ee73d6c
--- /dev/null
+++ b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/resources/fabric.mod.json
@@ -0,0 +1,38 @@
+{
+ "schemaVersion": 1,
+ "id": "osl-biomes",
+ "version": "0.1.0+mc1.8.2-pre5-mc15w51b",
+ "environment": "*",
+ "entrypoints": {
+ "init": [
+ "net.ornithemc.osl.biomes.impl.BiomeRegistryImpl::init"
+ ]
+ },
+ "mixins": [
+ "osl.biomes.mixins.json"
+ ],
+ "accessWidener": "osl.biomes.classtweaker",
+ "depends": {
+ "fabricloader": "\u003e\u003d0.18.0",
+ "minecraft": "\u003e\u003d1.8.2-rc.5 \u003c\u003d1.9-alpha.15.51.b",
+ "osl-core": "\u003e\u003d0.9.0",
+ "osl-entrypoints": "\u003e\u003d0.5.0",
+ "osl-lifecycle-events": "\u003e\u003d0.6.0",
+ "osl-executors": "\u003e\u003d0.1.0",
+ "osl-text-components": "\u003e\u003d0.1.0-",
+ "osl-networking": "\u003e\u003d0.10.0",
+ "osl-networking-impl": "\u003e\u003d0.2.0",
+ "osl-registries": "\u003e\u003d0.1.0"
+ },
+ "name": "OSL Biomes",
+ "description": "Biomes API and events.",
+ "authors": [
+ "OrnitheMC"
+ ],
+ "contact": {
+ "homepage": "https://ornithemc.net/",
+ "issues": "https://github.com/OrnitheMC/ornithe-standard-libraries/issues",
+ "sources": "https://github.com/OrnitheMC/ornithe-standard-libraries"
+ },
+ "license": "Apache-2.0"
+}
\ No newline at end of file
diff --git a/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/resources/osl.biomes.classtweaker b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/resources/osl.biomes.classtweaker
new file mode 100644
index 00000000..65138a95
--- /dev/null
+++ b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/resources/osl.biomes.classtweaker
@@ -0,0 +1,17 @@
+classTweaker v1 named
+
+transitive-accessible method net/minecraft/world/biome/Biome (I)V
+transitive-accessible method net/minecraft/world/biome/Biome setTemperatureAndDownfall (FF)Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setHeight (Lnet/minecraft/world/biome/Biome$Height;)Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome disableRain ()Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setSnowy ()Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setName (Ljava/lang/String;)Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setMutatedColor (I)Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setColor (I)Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setBaseColor (I)Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setColor (IZ)Lnet/minecraft/world/biome/Biome;
+
+transitive-inject-interface net/minecraft/world/biome/Biome net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl
+
+accessible field net/minecraft/world/biome/Biome BY_ID [Lnet/minecraft/world/biome/Biome;
+mutable field net/minecraft/world/biome/Biome id I
diff --git a/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/resources/osl.biomes.mixins.json b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/resources/osl.biomes.mixins.json
new file mode 100644
index 00000000..a674432b
--- /dev/null
+++ b/libraries/biomes/biomes-mc1.8.2-pre5-mc15w51b/src/main/resources/osl.biomes.mixins.json
@@ -0,0 +1,17 @@
+{
+ "required": true,
+ "minVersion": "0.8",
+ "package": "net.ornithemc.osl.biomes.impl.mixin",
+ "compatibilityLevel": "JAVA_8",
+ "plugin": "net.ornithemc.osl.biomes.impl.BiomesMixinPlugin",
+ "mixins": [
+ "common.BiomeMixin"
+ ],
+ "client": [
+ ],
+ "server": [
+ ],
+ "injectors": {
+ "defaultRequire": 1
+ }
+}
diff --git a/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/build.gradle b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/build.gradle
new file mode 100644
index 00000000..0a350fdb
--- /dev/null
+++ b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/build.gradle
@@ -0,0 +1 @@
+setUpModule(project)
diff --git a/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/gradle.properties b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/gradle.properties
new file mode 100644
index 00000000..98b53053
--- /dev/null
+++ b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/gradle.properties
@@ -0,0 +1,7 @@
+min_mc_version = 13w36a
+max_mc_version = 1.8.2-pre4
+
+minecraft_version = 1.7.2
+raven_build = 1
+sparrow_build = 1
+nests_build = 3
diff --git a/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java
new file mode 100644
index 00000000..0d49c6f2
--- /dev/null
+++ b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java
@@ -0,0 +1,34 @@
+package net.ornithemc.osl.biomes.api;
+
+import net.ornithemc.osl.core.api.events.Event;
+
+/**
+ * Events related to the biomes lifecycle.
+ */
+public final class BiomeEvents {
+
+ /**
+ * This event is invoked upon game start-up, after Vanilla biome registration is finished.
+ *
+ *
+ * Custom biome registration should be done in a listener of this event.
+ * Helper methods for registering biomes can be found in the {@linkplain
+ * BiomeRegistry} class.
+ *
+ *
+ * Listeners to this event should be registered in your mod's entrypoint,
+ * and can be done as follows:
+ *
+ *
+ * {@code
+ * BiomeEvents.REGISTER_BIOMES.register(() -> {
+ * BiomeRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new CookieBiome());
+ * });
+ * }
+ *
+ *
+ * @see BiomeRegistry
+ */
+ public static final Event REGISTER_BIOMES = Event.runnable();
+
+}
diff --git a/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java
new file mode 100644
index 00000000..86e85031
--- /dev/null
+++ b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java
@@ -0,0 +1,106 @@
+package net.ornithemc.osl.biomes.api;
+
+import java.util.Set;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.registries.api.registry.ResourceKey;
+
+/**
+ * Public access to the Biomes registry.
+ */
+public final class BiomeRegistry {
+
+ /**
+ * @return the numerical ID assigned to the given biome.
+ */
+ public static int getId(Biome biome) {
+ return BiomeRegistryImpl.getId(biome);
+ }
+
+ /**
+ * @return the namespaced ID assigned to the given biome.
+ */
+ public static NamespacedIdentifier getIdentifier(Biome biome) {
+ return BiomeRegistryImpl.getIdentifier(biome);
+ }
+
+ /**
+ * @return the resource key assigned to the given biome.
+ */
+ public static ResourceKey getKey(Biome biome) {
+ return BiomeRegistryImpl.getKey(biome);
+ }
+
+ /**
+ * @return the biome mapped to the given numerical ID.
+ */
+ public static Biome getBiome(int id) {
+ return BiomeRegistryImpl.getBiome(id);
+ }
+
+ /**
+ * @return the biome mapped to the given namespaced ID.
+ */
+ public static Biome getBiome(NamespacedIdentifier identifier) {
+ return BiomeRegistryImpl.getBiome(identifier);
+ }
+
+ /**
+ * @return the biome mapped to the given resource key.
+ */
+ public static Biome getBiome(ResourceKey key) {
+ return BiomeRegistryImpl.getBiome(key);
+ }
+
+ /**
+ * @return a set containing all namespaced IDs in the registry.
+ */
+ public static Set identifierSet() {
+ return BiomeRegistryImpl.identifierSet();
+ }
+
+ /**
+ * @return a set containing all resource keys in the registry.
+ */
+ public static Set> keySet() {
+ return BiomeRegistryImpl.keySet();
+ }
+
+ /**
+ * @param the biome type.
+ * @param identifier the namespaced ID of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ */
+ public static T register(NamespacedIdentifier identifier, T biome) {
+ return BiomeRegistryImpl.register(identifier, biome);
+ }
+
+ /**
+ * @param the biome type.
+ * @param key the resource key of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ */
+ public static T register(ResourceKey key, T biome) {
+ return BiomeRegistryImpl.register(key, biome);
+ }
+
+ /**
+ * @param the biome type.
+ * @param id the numerical ID of the biome.
+ * @param key the namespaced ID of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ *
+ * @deprecated use {@linkplain #register(NamespacedIdentifier, Biome)}
+ * or {@linkplain #register(ResourceKey, Biome)} instead.
+ */
+ @Deprecated
+ public static T register(int id, NamespacedIdentifier key, T biome) {
+ return BiomeRegistryImpl.register(id, key, biome);
+ }
+}
diff --git a/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java
new file mode 100644
index 00000000..06d6a59b
--- /dev/null
+++ b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java
@@ -0,0 +1,13 @@
+package net.ornithemc.osl.biomes.api.biome;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.registries.api.registry.Registry;
+
+public interface BiomeExtension {
+
+ Registry REGISTRY = BiomeRegistryImpl.REGISTRY;
+ int AUTO_ASSIGN_ID = -172;
+
+}
diff --git a/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java
new file mode 100644
index 00000000..46583dba
--- /dev/null
+++ b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java
@@ -0,0 +1,111 @@
+package net.ornithemc.osl.biomes.impl;
+
+import java.util.Set;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
+import net.ornithemc.osl.biomes.api.BiomeEvents;
+import net.ornithemc.osl.biomes.impl.biome.BiomeIdFixer;
+import net.ornithemc.osl.registries.api.registry.Registries;
+import net.ornithemc.osl.registries.api.registry.Registry;
+import net.ornithemc.osl.registries.api.registry.RegistryKeys;
+import net.ornithemc.osl.registries.api.registry.ResourceKey;
+import net.ornithemc.osl.registries.api.registry.SyncedRegistries;
+import net.ornithemc.osl.registries.impl.registry.RegistriesImpl;
+
+public final class BiomeRegistryImpl {
+
+ public static final Registry REGISTRY = Registries.registerSimple(RegistryKeys.BIOME, () -> Biome.BY_ID.getClass());
+
+ private static boolean locked = true;
+
+ public static int getId(Biome biome) {
+ return REGISTRY.getId(biome);
+ }
+
+ public static NamespacedIdentifier getIdentifier(Biome biome) {
+ return REGISTRY.getIdentifier(biome);
+ }
+
+ public static ResourceKey getKey(Biome biome) {
+ return REGISTRY.getKey(biome);
+ }
+
+ public static Biome getBiome(int id) {
+ return REGISTRY.get(id);
+ }
+
+ public static Biome getBiome(NamespacedIdentifier identifier) {
+ return REGISTRY.get(identifier);
+ }
+
+ public static Biome getBiome(ResourceKey key) {
+ return REGISTRY.get(key);
+ }
+
+ public static Set identifierSet() {
+ return REGISTRY.identifierSet();
+ }
+
+ public static Set> keySet() {
+ return REGISTRY.keySet();
+ }
+
+ @SuppressWarnings("deprecation")
+ public static T register(NamespacedIdentifier identifier, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ return Registry.register(REGISTRY, biome.id, identifier, biome);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public static T register(ResourceKey key, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ return Registry.register(REGISTRY, biome.id, key, biome);
+ }
+ }
+
+ @Deprecated
+ public static T register(int id, NamespacedIdentifier key, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ if (biome.id != id) {
+ throw new IllegalArgumentException("ID " + id + " does not match biome ID " + biome.id + " for " + key);
+ }
+
+ return Registry.register(REGISTRY, id, key, biome);
+ }
+ }
+
+ public static void init() {
+ SyncedRegistries.register(RegistryKeys.BIOME);
+ SyncedRegistries.registerFixer(RegistryKeys.BIOME, NamespacedIdentifiers.from("biome/id"), new BiomeIdFixer());
+ }
+
+ public static void unlock() {
+ locked = false;
+ }
+
+ public static void registerBiomes() {
+ VanillaBiomes.init();
+ BiomeEvents.REGISTER_BIOMES.invoker().run();
+ }
+
+ public static void registerUnknownBiomes() {
+ for (Biome biome : Biome.BY_ID) {
+ if (biome != null && REGISTRY.getIdentifier(biome) == null) {
+ NamespacedIdentifier identifier = NamespacedIdentifiers.from("osl", "biome_" + biome.id);
+
+ RegistriesImpl.LOGGER.warn("Biome {}/{}", biome.id, biome.getClass().getSimpleName() + " was not registered to OSL's Biome registry! Adding it as '" + identifier + "'...");
+ BiomeRegistryImpl.register(identifier, biome);
+ }
+ }
+ }
+}
diff --git a/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/BiomesMixinPlugin.java b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/BiomesMixinPlugin.java
new file mode 100644
index 00000000..19b6a9e8
--- /dev/null
+++ b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/BiomesMixinPlugin.java
@@ -0,0 +1,54 @@
+package net.ornithemc.osl.biomes.impl;
+
+import java.util.List;
+import java.util.Set;
+
+import org.objectweb.asm.tree.ClassNode;
+
+import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
+import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
+
+import net.ornithemc.osl.core.impl.util.MinecraftVersion;
+
+public class BiomesMixinPlugin implements IMixinConfigPlugin {
+
+ public static final boolean BIOME_IDS_BEYOND_255_SUPPORTED = false;
+
+ @Override
+ public void onLoad(String mixinPackage) {
+ }
+
+ @Override
+ public String getRefMapperConfig() {
+ return null;
+ }
+
+ @Override
+ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
+ if ("net.ornithemc.osl.biomes.impl.mixin.common.BiomeMixinNew".equals(mixinClassName)) {
+ return MinecraftVersion.resolve().compareTo("14w05a") >= 0;
+ }
+ if ("net.ornithemc.osl.biomes.impl.mixin.common.BiomeMixinOld".equals(mixinClassName)) {
+ return MinecraftVersion.resolve().compareTo("14w05a") < 0;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void acceptTargets(Set myTargets, Set otherTargets) {
+ }
+
+ @Override
+ public List getMixins() {
+ return null;
+ }
+
+ @Override
+ public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
+ }
+
+ @Override
+ public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
+ }
+}
diff --git a/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/VanillaBiomes.java b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/VanillaBiomes.java
new file mode 100644
index 00000000..a17199dd
--- /dev/null
+++ b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/VanillaBiomes.java
@@ -0,0 +1,146 @@
+package net.ornithemc.osl.biomes.impl;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
+
+public final class VanillaBiomes {
+
+ /**
+ * Namespaced IDs were introduced in 1.9. Before then, the numerical IDs
+ * were the only unique identifiers for biomes. Here we assign namespaced
+ * IDs to pre-1.9 biomes, matching the 1.9 IDs where possible.
+ */
+ private static final String[] IDENTIFIERS = {
+ // grouped per 10 for easier lookup
+
+ "ocean",
+ "plains",
+ "desert",
+ "extreme_hills",
+ "forest",
+ "taiga",
+ "swampland",
+ "river",
+ "hell",
+ "sky",
+
+ "frozen_ocean",
+ "frozen_river",
+ "ice_flats",
+ "ice_mountains",
+ "mushroom_island",
+ "mushroom_island_shore",
+ "beaches",
+ "desert_hills",
+ "forest_hills",
+ "taiga_hills",
+
+ "smaller_extreme_hills",
+ "jungle",
+ "jungle_hills",
+ "jungle_edge",
+ "deep_ocean",
+ "stone_beach",
+ "cold_beach",
+ "birch_forest",
+ "birch_forest_hills",
+ "roofed_forest",
+
+ "taiga_cold",
+ "taiga_cold_hills",
+ "redwood_taiga",
+ "redwood_taiga_hills",
+ "extreme_hills_with_trees",
+ "savanna",
+ "savanna_rock",
+ "mesa",
+ "mesa_rock",
+ "mesa_clear_rock"
+ };
+ private static final String[] MUTATED_IDENTIFIERS = {
+ null,
+ "mutated_plains",
+ "mutated_desert",
+ "mutated_extreme_hills",
+ "mutated_forest",
+ "mutated_taiga",
+ "mutated_swampland",
+ null,
+ null,
+ null,
+
+ null,
+ null,
+ "mutated_ice_flats",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+
+ null,
+ "mutated_jungle",
+ null,
+ "mutated_jungle_edge",
+ null,
+ null,
+ null,
+ "mutated_birch_forest",
+ "mutated_birch_forest_hills",
+ "mutated_roofed_forest",
+
+ "mutated_taiga_cold",
+ null,
+ "mutated_redwood_taiga",
+ "mutated_redwood_taiga_hills",
+ "mutated_extreme_hills_with_trees",
+ "mutated_savanna",
+ "mutated_savanna_rock",
+ "mutated_mesa",
+ "mutated_mesa_rock",
+ "mutated_mesa_clear_rock"
+ };
+
+ public static final int MAX_ID = 255;
+ public static final int MUTATED_ID_OFFSET = 128;
+
+ static void init() {
+ for (Field f : Biome.class.getDeclaredFields()) {
+ if (Modifier.isStatic(f.getModifiers()) && Biome.class.isAssignableFrom(f.getType())) {
+ try {
+ Biome biome = (Biome) f.get(null);
+
+ if (biome != null) {
+ register(biome);
+ }
+ } catch (Throwable t) {
+ }
+ }
+ }
+ }
+
+ private static void register(Biome biome) {
+ if (biome.id >= 0 && biome.id < IDENTIFIERS.length) {
+ String identifier = IDENTIFIERS[biome.id];
+
+ if (identifier != null) {
+ BiomeRegistryImpl.register(NamespacedIdentifiers.from(identifier), biome);
+ }
+ }
+
+ if (biome.id >= 0 && biome.id < MUTATED_IDENTIFIERS.length) {
+ Biome mutated = Biome.BY_ID[biome.id + MUTATED_ID_OFFSET];
+ String identifier = MUTATED_IDENTIFIERS[biome.id];
+
+ if (identifier != null) {
+ BiomeRegistryImpl.register(NamespacedIdentifiers.from(identifier), mutated);
+ }
+ }
+ }
+}
diff --git a/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java
new file mode 100644
index 00000000..1b77c6af
--- /dev/null
+++ b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java
@@ -0,0 +1,6 @@
+package net.ornithemc.osl.biomes.impl.biome;
+
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+
+public interface BiomeExtensionImpl extends BiomeExtension {
+}
diff --git a/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeIdFixer.java b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeIdFixer.java
new file mode 100644
index 00000000..1bacf15f
--- /dev/null
+++ b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeIdFixer.java
@@ -0,0 +1,19 @@
+package net.ornithemc.osl.biomes.impl.biome;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.registries.api.registry.sync.IdFixer;
+
+public class BiomeIdFixer implements IdFixer {
+
+ @Override
+ public void apply() {
+ for (int id = 0; id < Biome.BY_ID.length; id++) {
+ Biome biome = Biome.BY_ID[id];
+
+ if (biome != null) {
+ biome.id = id;
+ }
+ }
+ }
+}
diff --git a/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java
new file mode 100644
index 00000000..6cdc0141
--- /dev/null
+++ b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java
@@ -0,0 +1,87 @@
+package net.ornithemc.osl.biomes.impl.mixin.common;
+
+import org.objectweb.asm.Opcodes;
+
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Mutable;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.At.Shift;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.ModifyVariable;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+import net.ornithemc.osl.biomes.impl.BiomesMixinPlugin;
+import net.ornithemc.osl.biomes.impl.VanillaBiomes;
+import net.ornithemc.osl.registries.api.registry.RegistryKeys;
+import net.ornithemc.osl.registries.api.registry.SyncedRegistries;
+import net.ornithemc.osl.registries.api.registry.sync.ArrayMapper;
+import net.ornithemc.osl.registries.api.registry.sync.DynamicArray;
+
+@Mixin(Biome.class)
+public class BiomeMixin implements BiomeExtension {
+
+ @Shadow @Final @Mutable
+ private static Biome[] BY_ID;
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "TAIL"
+ )
+ )
+ private static void osl$biomes$registerArrayMappers(CallbackInfo ci) {
+ SyncedRegistries.registerMapper(RegistryKeys.BIOME, NamespacedIdentifiers.from("biome/by_id"), ArrayMapper.of(() -> BY_ID, a -> BY_ID = a));
+ }
+
+ @ModifyVariable(
+ method = "",
+ argsOnly = true,
+ ordinal = 0,
+ at = @At(
+ value = "INVOKE",
+ target = "Ljava/lang/Object;()V",
+ shift = Shift.AFTER
+ )
+ )
+ private int osl$biomes$handleAutoAssignId(int id) {
+ if (id == AUTO_ASSIGN_ID) {
+ // the Biome[] array must contain all biomes so this should
+ // give us a valid ID for the Biome registry to use.
+ id = DynamicArray.length(BY_ID);
+
+ // keep 0-255 free for all Vanilla biomes
+ if (BiomesMixinPlugin.BIOME_IDS_BEYOND_255_SUPPORTED && id <= VanillaBiomes.MAX_ID) {
+ id = VanillaBiomes.MAX_ID + 1;
+ }
+ }
+
+ if (!BiomesMixinPlugin.BIOME_IDS_BEYOND_255_SUPPORTED && id > VanillaBiomes.MAX_ID) {
+ throw new IllegalStateException("Biome IDs above 255 are not supported at this time!"
+ + " Biome IDs should be limited to the range 0-255"
+ + " unless the save format has been modified to support IDs beyond 255.");
+ }
+
+ return id;
+ }
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "FIELD",
+ target = "Lnet/minecraft/world/biome/Biome;BY_ID:[Lnet/minecraft/world/biome/Biome;",
+ opcode = Opcodes.GETSTATIC,
+ args = "array=set"
+ )
+ )
+ private void osl$biomes$growArrays(int id, CallbackInfo ci) {
+ int capacity = id + 1;
+
+ BY_ID = DynamicArray.grow(BY_ID, capacity);
+ }
+}
diff --git a/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixinNew.java b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixinNew.java
new file mode 100644
index 00000000..3d1e3499
--- /dev/null
+++ b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixinNew.java
@@ -0,0 +1,63 @@
+package net.ornithemc.osl.biomes.impl.mixin.common;
+
+import org.objectweb.asm.Opcodes;
+
+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;
+
+import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
+import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.biomes.impl.BiomesMixinPlugin;
+import net.ornithemc.osl.biomes.impl.VanillaBiomes;
+import net.ornithemc.osl.registries.api.registry.sync.DynamicArray;
+
+@Mixin(Biome.class)
+public class BiomeMixinNew {
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "HEAD"
+ )
+ )
+ private static void osl$biomes$unlockBiomeRegistry(CallbackInfo ci) {
+ BiomeRegistryImpl.unlock();
+ }
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "FIELD",
+ target = "Lnet/minecraft/world/biome/Biome;BY_ID:[Lnet/minecraft/world/biome/Biome;",
+ opcode = Opcodes.GETSTATIC,
+ ordinal = 0
+ )
+ )
+ private static void osl$biomes$registerBiomes(CallbackInfo ci) {
+ BiomeRegistryImpl.registerBiomes();
+ BiomeRegistryImpl.registerUnknownBiomes();
+ }
+
+ @WrapOperation(
+ method = "mutate()Lnet/minecraft/world/biome/Biome;",
+ at = @At(
+ value = "INVOKE",
+ target = "Lnet/minecraft/world/biome/Biome;mutate(I)Lnet/minecraft/world/biome/Biome;"
+ )
+ )
+ private static Biome osl$biomes$handleAutoAssignIdForMutatedBiomes(Biome original, int id, Operation op) {
+ if (BiomesMixinPlugin.BIOME_IDS_BEYOND_255_SUPPORTED && original.id > VanillaBiomes.MAX_ID) {
+ // the Biome[] array must contain all biomes so this should
+ // give us a valid ID for the Biome registry to use.
+ id = DynamicArray.length(Biome.BY_ID);
+ }
+
+ return op.call(original, id);
+ }
+}
diff --git a/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixinOld.java b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixinOld.java
new file mode 100644
index 00000000..08eab329
--- /dev/null
+++ b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixinOld.java
@@ -0,0 +1,64 @@
+package net.ornithemc.osl.biomes.impl.mixin.common;
+
+import org.objectweb.asm.Opcodes;
+
+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;
+
+import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
+import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
+
+import net.minecraft.world.biome.Biome;
+import net.minecraft.world.biome.MutatedBiome;
+
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.biomes.impl.BiomesMixinPlugin;
+import net.ornithemc.osl.biomes.impl.VanillaBiomes;
+import net.ornithemc.osl.registries.api.registry.sync.DynamicArray;
+
+@Mixin(Biome.class)
+public class BiomeMixinOld {
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "HEAD"
+ )
+ )
+ private static void osl$biomes$unlockBiomeRegistry(CallbackInfo ci) {
+ BiomeRegistryImpl.unlock();
+ }
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "FIELD",
+ target = "Lnet/minecraft/world/biome/Biome;BY_ID:[Lnet/minecraft/world/biome/Biome;",
+ opcode = Opcodes.GETSTATIC,
+ ordinal = 0
+ )
+ )
+ private static void osl$biomes$registerBiomes(CallbackInfo ci) {
+ BiomeRegistryImpl.registerBiomes();
+ BiomeRegistryImpl.registerUnknownBiomes();
+ }
+
+ @WrapOperation(
+ method = "mutate",
+ at = @At(
+ value = "NEW",
+ target = "net/minecraft/world/biome/MutatedBiome"
+ )
+ )
+ private static MutatedBiome osl$biomes$handleAutoAssignIdForMutatedBiomes(int id, Biome original, Operation op) {
+ if (BiomesMixinPlugin.BIOME_IDS_BEYOND_255_SUPPORTED && original.id > VanillaBiomes.MAX_ID) {
+ // the Biome[] array must contain all biomes so this should
+ // give us a valid ID for the Biome registry to use.
+ id = DynamicArray.length(Biome.BY_ID);
+ }
+
+ return op.call(id, original);
+ }
+}
diff --git a/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/resources/fabric.mod.json b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/resources/fabric.mod.json
new file mode 100644
index 00000000..19d52978
--- /dev/null
+++ b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/resources/fabric.mod.json
@@ -0,0 +1,38 @@
+{
+ "schemaVersion": 1,
+ "id": "osl-biomes",
+ "version": "0.1.0+mc13w36a-mc1.8.2-pre4",
+ "environment": "*",
+ "entrypoints": {
+ "init": [
+ "net.ornithemc.osl.biomes.impl.BiomeRegistryImpl::init"
+ ]
+ },
+ "mixins": [
+ "osl.biomes.mixins.json"
+ ],
+ "accessWidener": "osl.biomes.classtweaker",
+ "depends": {
+ "fabricloader": "\u003e\u003d0.18.0",
+ "minecraft": "\u003e\u003d1.7-alpha.13.36.a \u003c\u003d1.8.2-rc.4",
+ "osl-core": "\u003e\u003d0.9.0",
+ "osl-entrypoints": "\u003e\u003d0.5.0",
+ "osl-lifecycle-events": "\u003e\u003d0.6.0",
+ "osl-executors": "\u003e\u003d0.1.0",
+ "osl-text-components": "\u003e\u003d0.1.0-",
+ "osl-networking": "\u003e\u003d0.10.0",
+ "osl-networking-impl": "\u003e\u003d0.2.0",
+ "osl-registries": "\u003e\u003d0.1.0"
+ },
+ "name": "OSL Biomes",
+ "description": "Biomes API and events.",
+ "authors": [
+ "OrnitheMC"
+ ],
+ "contact": {
+ "homepage": "https://ornithemc.net/",
+ "issues": "https://github.com/OrnitheMC/ornithe-standard-libraries/issues",
+ "sources": "https://github.com/OrnitheMC/ornithe-standard-libraries"
+ },
+ "license": "Apache-2.0"
+}
\ No newline at end of file
diff --git a/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/resources/osl.biomes.classtweaker b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/resources/osl.biomes.classtweaker
new file mode 100644
index 00000000..65138a95
--- /dev/null
+++ b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/resources/osl.biomes.classtweaker
@@ -0,0 +1,17 @@
+classTweaker v1 named
+
+transitive-accessible method net/minecraft/world/biome/Biome (I)V
+transitive-accessible method net/minecraft/world/biome/Biome setTemperatureAndDownfall (FF)Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setHeight (Lnet/minecraft/world/biome/Biome$Height;)Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome disableRain ()Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setSnowy ()Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setName (Ljava/lang/String;)Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setMutatedColor (I)Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setColor (I)Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setBaseColor (I)Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setColor (IZ)Lnet/minecraft/world/biome/Biome;
+
+transitive-inject-interface net/minecraft/world/biome/Biome net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl
+
+accessible field net/minecraft/world/biome/Biome BY_ID [Lnet/minecraft/world/biome/Biome;
+mutable field net/minecraft/world/biome/Biome id I
diff --git a/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/resources/osl.biomes.mixins.json b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/resources/osl.biomes.mixins.json
new file mode 100644
index 00000000..a674432b
--- /dev/null
+++ b/libraries/biomes/biomes-mc13w36a-mc1.8.2-pre4/src/main/resources/osl.biomes.mixins.json
@@ -0,0 +1,17 @@
+{
+ "required": true,
+ "minVersion": "0.8",
+ "package": "net.ornithemc.osl.biomes.impl.mixin",
+ "compatibilityLevel": "JAVA_8",
+ "plugin": "net.ornithemc.osl.biomes.impl.BiomesMixinPlugin",
+ "mixins": [
+ "common.BiomeMixin"
+ ],
+ "client": [
+ ],
+ "server": [
+ ],
+ "injectors": {
+ "defaultRequire": 1
+ }
+}
diff --git a/libraries/biomes/biomes-mc16w02a-mc18w05a/build.gradle b/libraries/biomes/biomes-mc16w02a-mc18w05a/build.gradle
new file mode 100644
index 00000000..0a350fdb
--- /dev/null
+++ b/libraries/biomes/biomes-mc16w02a-mc18w05a/build.gradle
@@ -0,0 +1 @@
+setUpModule(project)
diff --git a/libraries/biomes/biomes-mc16w02a-mc18w05a/gradle.properties b/libraries/biomes/biomes-mc16w02a-mc18w05a/gradle.properties
new file mode 100644
index 00000000..5d40c0ac
--- /dev/null
+++ b/libraries/biomes/biomes-mc16w02a-mc18w05a/gradle.properties
@@ -0,0 +1,4 @@
+min_mc_version = 16w02a
+max_mc_version = 18w05a
+
+minecraft_version = 1.12.2
diff --git a/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java
new file mode 100644
index 00000000..0d49c6f2
--- /dev/null
+++ b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java
@@ -0,0 +1,34 @@
+package net.ornithemc.osl.biomes.api;
+
+import net.ornithemc.osl.core.api.events.Event;
+
+/**
+ * Events related to the biomes lifecycle.
+ */
+public final class BiomeEvents {
+
+ /**
+ * This event is invoked upon game start-up, after Vanilla biome registration is finished.
+ *
+ *
+ * Custom biome registration should be done in a listener of this event.
+ * Helper methods for registering biomes can be found in the {@linkplain
+ * BiomeRegistry} class.
+ *
+ *
+ * Listeners to this event should be registered in your mod's entrypoint,
+ * and can be done as follows:
+ *
+ *
+ * {@code
+ * BiomeEvents.REGISTER_BIOMES.register(() -> {
+ * BiomeRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new CookieBiome());
+ * });
+ * }
+ *
+ *
+ * @see BiomeRegistry
+ */
+ public static final Event REGISTER_BIOMES = Event.runnable();
+
+}
diff --git a/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java
new file mode 100644
index 00000000..bc8fb566
--- /dev/null
+++ b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java
@@ -0,0 +1,91 @@
+package net.ornithemc.osl.biomes.api;
+
+import java.util.Set;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.registries.api.registry.ResourceKey;
+
+/**
+ * Public access to the Biomes registry.
+ */
+public final class BiomeRegistry {
+
+ /**
+ * @return the numerical ID assigned to the given biome.
+ */
+ public static int getId(Biome biome) {
+ return BiomeRegistryImpl.getId(biome);
+ }
+
+ /**
+ * @return the namespaced ID assigned to the given biome.
+ */
+ public static NamespacedIdentifier getIdentifier(Biome biome) {
+ return BiomeRegistryImpl.getIdentifier(biome);
+ }
+
+ /**
+ * @return the resource key assigned to the given biome.
+ */
+ public static ResourceKey getKey(Biome biome) {
+ return BiomeRegistryImpl.getKey(biome);
+ }
+
+ /**
+ * @return the biome mapped to the given numerical ID.
+ */
+ public static Biome getBiome(int id) {
+ return BiomeRegistryImpl.getBiome(id);
+ }
+
+ /**
+ * @return the biome mapped to the given namespaced ID.
+ */
+ public static Biome getBiome(NamespacedIdentifier identifier) {
+ return BiomeRegistryImpl.getBiome(identifier);
+ }
+
+ /**
+ * @return the biome mapped to the given resource key.
+ */
+ public static Biome getBiome(ResourceKey key) {
+ return BiomeRegistryImpl.getBiome(key);
+ }
+
+ /**
+ * @return a set containing all namespaced IDs in the registry.
+ */
+ public static Set identifierSet() {
+ return BiomeRegistryImpl.identifierSet();
+ }
+
+ /**
+ * @return a set containing all resource keys in the registry.
+ */
+ public static Set> keySet() {
+ return BiomeRegistryImpl.keySet();
+ }
+
+ /**
+ * @param the biome type.
+ * @param identifier the namespaced ID of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ */
+ public static T register(NamespacedIdentifier identifier, T biome) {
+ return BiomeRegistryImpl.register(identifier, biome);
+ }
+
+ /**
+ * @param the biome type.
+ * @param key the resource key of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ */
+ public static T register(ResourceKey key, T biome) {
+ return BiomeRegistryImpl.register(key, biome);
+ }
+}
diff --git a/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java
new file mode 100644
index 00000000..4e8867f6
--- /dev/null
+++ b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java
@@ -0,0 +1,14 @@
+package net.ornithemc.osl.biomes.api.biome;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+
+public interface BiomeExtension {
+
+ interface SettingsExtension {
+
+ Biome.Settings parent(NamespacedIdentifier identifier);
+
+ }
+}
diff --git a/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/BiomeIdRegistry.java b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/BiomeIdRegistry.java
new file mode 100644
index 00000000..0ca2ddfc
--- /dev/null
+++ b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/BiomeIdRegistry.java
@@ -0,0 +1,20 @@
+package net.ornithemc.osl.biomes.impl;
+
+import net.minecraft.resource.Identifier;
+import net.minecraft.util.registry.IdRegistry;
+import net.minecraft.world.biome.Biome;
+
+/**
+ * The biome registry is created and populated in Biome's class initializer.
+ * This breaks OSL's usual pattern of registering the registry in the API entrypoint but
+ * triggering registry population during bootstrapping, since OSL has to wrap the Vanilla
+ * registry which is not possible without triggering Biome class load and registry
+ * population.
+ * The solution: move the Vanilla registry to another class and replace the IdRegistry
+ * reference in Biome with this one.
+ */
+public final class BiomeIdRegistry {
+
+ public static final IdRegistry REGISTRY = new IdRegistry<>();
+
+}
diff --git a/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java
new file mode 100644
index 00000000..c00d2e7d
--- /dev/null
+++ b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java
@@ -0,0 +1,99 @@
+package net.ornithemc.osl.biomes.impl;
+
+import java.util.Set;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.biomes.api.BiomeEvents;
+import net.ornithemc.osl.registries.api.registry.Registry;
+import net.ornithemc.osl.registries.api.registry.RegistryKeys;
+import net.ornithemc.osl.registries.api.registry.ResourceKey;
+import net.ornithemc.osl.registries.api.registry.SyncedRegistries;
+import net.ornithemc.osl.registries.impl.registry.VanillaRegistries;
+
+public final class BiomeRegistryImpl {
+
+ public static final Registry REGISTRY = VanillaRegistries.registerSimple(RegistryKeys.BIOME, BiomeIdRegistry.REGISTRY, () -> Biome.REGISTRY);
+
+ private static boolean locked = true;
+
+ public static int getId(Biome biome) {
+ return REGISTRY.getId(biome);
+ }
+
+ public static NamespacedIdentifier getIdentifier(Biome biome) {
+ return REGISTRY.getIdentifier(biome);
+ }
+
+ public static ResourceKey getKey(Biome biome) {
+ return REGISTRY.getKey(biome);
+ }
+
+ public static Biome getBiome(int id) {
+ return REGISTRY.get(id);
+ }
+
+ public static Biome getBiome(NamespacedIdentifier identifier) {
+ return REGISTRY.get(identifier);
+ }
+
+ public static Biome getBiome(ResourceKey key) {
+ return REGISTRY.get(key);
+ }
+
+ public static Set identifierSet() {
+ return REGISTRY.identifierSet();
+ }
+
+ public static Set> keySet() {
+ return REGISTRY.keySet();
+ }
+
+ public static T register(NamespacedIdentifier identifier, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ if (biome.isMutated()) {
+ registerBiomeMutation(identifier, biome);
+ }
+
+ return Registry.register(REGISTRY, identifier, biome);
+ }
+ }
+
+ public static T register(ResourceKey key, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ if (biome.isMutated()) {
+ registerBiomeMutation(key.identifier(), biome);
+ }
+
+ return Registry.register(REGISTRY, key, biome);
+ }
+ }
+
+ private static void registerBiomeMutation(NamespacedIdentifier identifier, Biome biome) {
+ NamespacedIdentifier parentIdentifier = biome.osl$biomes$getParentIdentifier();
+ Biome parent = REGISTRY.get(parentIdentifier);
+
+ if (parent == null) {
+ throw new IllegalStateException("Error registering mutated biome " + identifier + ": parent " + parentIdentifier + " does not exist!");
+ } else {
+ Biome.MUTATED_BIOMES.put(biome, REGISTRY.getId(parent));
+ }
+ }
+
+ public static void init() {
+ SyncedRegistries.register(RegistryKeys.BIOME);
+ }
+
+ public static void unlock() {
+ locked = false;
+ }
+
+ public static void registerBiomes() {
+ BiomeEvents.REGISTER_BIOMES.invoker().run();
+ }
+}
diff --git a/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/access/BiomeAccess.java b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/access/BiomeAccess.java
new file mode 100644
index 00000000..e64d1669
--- /dev/null
+++ b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/access/BiomeAccess.java
@@ -0,0 +1,10 @@
+package net.ornithemc.osl.biomes.impl.access;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+
+public interface BiomeAccess {
+
+ default NamespacedIdentifier osl$biomes$getParentIdentifier() {
+ throw new AbstractMethodError();
+ }
+}
diff --git a/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java
new file mode 100644
index 00000000..bc8a9dc4
--- /dev/null
+++ b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java
@@ -0,0 +1,17 @@
+package net.ornithemc.osl.biomes.impl.biome;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+
+public interface BiomeExtensionImpl extends BiomeExtension {
+
+ interface SettingsExtensionImpl extends SettingsExtension {
+
+ @Override
+ default Biome.Settings parent(NamespacedIdentifier identifier) {
+ throw new AbstractMethodError();
+ }
+ }
+}
diff --git a/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java
new file mode 100644
index 00000000..e1d87b9e
--- /dev/null
+++ b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java
@@ -0,0 +1,74 @@
+package net.ornithemc.osl.biomes.impl.mixin.common;
+
+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.Inject;
+import org.spongepowered.asm.mixin.injection.Redirect;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import net.minecraft.resource.Identifier;
+import net.minecraft.util.Id2ObjectBiMap;
+import net.minecraft.util.registry.IdRegistry;
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+import net.ornithemc.osl.biomes.impl.BiomeIdRegistry;
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.biomes.impl.access.BiomeAccess;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
+import net.ornithemc.osl.registries.api.registry.RegistryKeys;
+import net.ornithemc.osl.registries.api.registry.SyncedRegistries;
+import net.ornithemc.osl.registries.api.registry.sync.Id2ObjectBiMapMapper;
+
+@Mixin(Biome.class)
+public class BiomeMixin implements BiomeExtension, BiomeAccess {
+
+ @Shadow @Final
+ public static Id2ObjectBiMap MUTATED_BIOMES;
+
+ @Shadow @Final
+ private String parent;
+
+ @Redirect(
+ method = "",
+ at = @At(
+ value = "NEW",
+ target = "net/minecraft/util/registry/IdRegistry"
+ )
+ )
+ private static IdRegistry osl$biomes$replaceIdRegistry() {
+ // this allows us to register the biome registry in
+ // the API entrypoint without triggering a Biome class load
+ return BiomeIdRegistry.REGISTRY;
+ }
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "HEAD"
+ )
+ )
+ private static void osl$biomes$unlockBiomeRegistry(CallbackInfo ci) {
+ BiomeRegistryImpl.unlock();
+ }
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "TAIL"
+ )
+ )
+ private static void osl$biomes$registerBiomesAndMappers(CallbackInfo ci) {
+ BiomeRegistryImpl.registerBiomes();
+
+ SyncedRegistries.registerMapper(RegistryKeys.BIOME, NamespacedIdentifiers.from("mutated_biome"), Id2ObjectBiMapMapper.of(MUTATED_BIOMES));
+ }
+
+ @Override
+ public NamespacedIdentifier osl$biomes$getParentIdentifier() {
+ return this.parent == null ? null : NamespacedIdentifiers.parse(this.parent);
+ }
+}
diff --git a/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeSettingsMixin.java b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeSettingsMixin.java
new file mode 100644
index 00000000..f906a416
--- /dev/null
+++ b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeSettingsMixin.java
@@ -0,0 +1,22 @@
+package net.ornithemc.osl.biomes.impl.mixin.common;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+
+@Mixin(Biome.Settings.class)
+public class BiomeSettingsMixin implements BiomeExtension.SettingsExtension {
+
+ @Shadow
+ public String parent;
+
+ @Override
+ public Biome.Settings parent(NamespacedIdentifier identifier) {
+ this.parent = identifier.toString();
+ return (Biome.Settings) (Object) this;
+ }
+}
diff --git a/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/resources/fabric.mod.json b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/resources/fabric.mod.json
new file mode 100644
index 00000000..98f2768e
--- /dev/null
+++ b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/resources/fabric.mod.json
@@ -0,0 +1,38 @@
+{
+ "schemaVersion": 1,
+ "id": "osl-biomes",
+ "version": "0.1.0+mc16w02a-mc18w05a",
+ "environment": "*",
+ "entrypoints": {
+ "init": [
+ "net.ornithemc.osl.biomes.impl.BiomeRegistryImpl::init"
+ ]
+ },
+ "mixins": [
+ "osl.biomes.mixins.json"
+ ],
+ "accessWidener": "osl.biomes.classtweaker",
+ "depends": {
+ "fabricloader": "\u003e\u003d0.18.0",
+ "minecraft": "\u003e\u003d1.9-alpha.16.2.a \u003c\u003d1.13-alpha.18.5.a",
+ "osl-core": "\u003e\u003d0.9.0",
+ "osl-entrypoints": "\u003e\u003d0.5.0",
+ "osl-lifecycle-events": "\u003e\u003d0.6.0",
+ "osl-executors": "\u003e\u003d0.1.0",
+ "osl-text-components": "\u003e\u003d0.1.0-",
+ "osl-networking": "\u003e\u003d0.10.0",
+ "osl-networking-impl": "\u003e\u003d0.2.0",
+ "osl-registries": "\u003e\u003d0.1.0"
+ },
+ "name": "OSL Biomes",
+ "description": "Biomes API and events.",
+ "authors": [
+ "OrnitheMC"
+ ],
+ "contact": {
+ "homepage": "https://ornithemc.net/",
+ "issues": "https://github.com/OrnitheMC/ornithe-standard-libraries/issues",
+ "sources": "https://github.com/OrnitheMC/ornithe-standard-libraries"
+ },
+ "license": "Apache-2.0"
+}
\ No newline at end of file
diff --git a/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/resources/osl.biomes.classtweaker b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/resources/osl.biomes.classtweaker
new file mode 100644
index 00000000..bf7db77f
--- /dev/null
+++ b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/resources/osl.biomes.classtweaker
@@ -0,0 +1,16 @@
+classTweaker v1 named
+
+transitive-accessible method net/minecraft/world/biome/Biome (Lnet/minecraft/world/biome/Biome$Settings;)V
+transitive-accessible method net/minecraft/world/biome/Biome$Settings temperature (F)Lnet/minecraft/world/biome/Biome$Settings;
+transitive-accessible method net/minecraft/world/biome/Biome$Settings downfall (F)Lnet/minecraft/world/biome/Biome$Settings;
+transitive-accessible method net/minecraft/world/biome/Biome$Settings depth (F)Lnet/minecraft/world/biome/Biome$Settings;
+transitive-accessible method net/minecraft/world/biome/Biome$Settings scale (F)Lnet/minecraft/world/biome/Biome$Settings;
+transitive-accessible method net/minecraft/world/biome/Biome$Settings hasRain ()Lnet/minecraft/world/biome/Biome$Settings;
+transitive-accessible method net/minecraft/world/biome/Biome$Settings snowy ()Lnet/minecraft/world/biome/Biome$Settings;
+transitive-accessible method net/minecraft/world/biome/Biome$Settings waterColor (I)Lnet/minecraft/world/biome/Biome$Settings;
+transitive-accessible method net/minecraft/world/biome/Biome$Settings parent (Ljava/lang/String;)Lnet/minecraft/world/biome/Biome$Settings;
+
+transitive-inject-interface net/minecraft/world/biome/Biome net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl
+transitive-inject-interface net/minecraft/world/biome/Biome$Settings net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl$SettingsExtensionImpl
+
+inject-interface net/minecraft/world/biome/Biome net/ornithemc/osl/biomes/impl/access/BiomeAccess
diff --git a/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/resources/osl.biomes.mixins.json b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/resources/osl.biomes.mixins.json
new file mode 100644
index 00000000..a0b6d1a0
--- /dev/null
+++ b/libraries/biomes/biomes-mc16w02a-mc18w05a/src/main/resources/osl.biomes.mixins.json
@@ -0,0 +1,18 @@
+{
+ "required": true,
+ "minVersion": "0.8",
+ "package": "net.ornithemc.osl.biomes.impl.mixin",
+ "compatibilityLevel": "JAVA_8",
+ "plugin": "net.ornithemc.osl.biomes.impl.BiomesMixinPlugin",
+ "mixins": [
+ "common.BiomeMixin",
+ "common.BiomeSettingsMixin"
+ ],
+ "client": [
+ ],
+ "server": [
+ ],
+ "injectors": {
+ "defaultRequire": 1
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w06a-mc18w31a/build.gradle b/libraries/biomes/biomes-mc18w06a-mc18w31a/build.gradle
new file mode 100644
index 00000000..0a350fdb
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w06a-mc18w31a/build.gradle
@@ -0,0 +1 @@
+setUpModule(project)
diff --git a/libraries/biomes/biomes-mc18w06a-mc18w31a/gradle.properties b/libraries/biomes/biomes-mc18w06a-mc18w31a/gradle.properties
new file mode 100644
index 00000000..372a4ad3
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w06a-mc18w31a/gradle.properties
@@ -0,0 +1,4 @@
+min_mc_version = 18w06a
+max_mc_version = 18w31a
+
+minecraft_version = 1.13
diff --git a/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java
new file mode 100644
index 00000000..0d49c6f2
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java
@@ -0,0 +1,34 @@
+package net.ornithemc.osl.biomes.api;
+
+import net.ornithemc.osl.core.api.events.Event;
+
+/**
+ * Events related to the biomes lifecycle.
+ */
+public final class BiomeEvents {
+
+ /**
+ * This event is invoked upon game start-up, after Vanilla biome registration is finished.
+ *
+ *
+ * Custom biome registration should be done in a listener of this event.
+ * Helper methods for registering biomes can be found in the {@linkplain
+ * BiomeRegistry} class.
+ *
+ *
+ * Listeners to this event should be registered in your mod's entrypoint,
+ * and can be done as follows:
+ *
+ *
+ * {@code
+ * BiomeEvents.REGISTER_BIOMES.register(() -> {
+ * BiomeRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new CookieBiome());
+ * });
+ * }
+ *
+ *
+ * @see BiomeRegistry
+ */
+ public static final Event REGISTER_BIOMES = Event.runnable();
+
+}
diff --git a/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java
new file mode 100644
index 00000000..bc8fb566
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java
@@ -0,0 +1,91 @@
+package net.ornithemc.osl.biomes.api;
+
+import java.util.Set;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.registries.api.registry.ResourceKey;
+
+/**
+ * Public access to the Biomes registry.
+ */
+public final class BiomeRegistry {
+
+ /**
+ * @return the numerical ID assigned to the given biome.
+ */
+ public static int getId(Biome biome) {
+ return BiomeRegistryImpl.getId(biome);
+ }
+
+ /**
+ * @return the namespaced ID assigned to the given biome.
+ */
+ public static NamespacedIdentifier getIdentifier(Biome biome) {
+ return BiomeRegistryImpl.getIdentifier(biome);
+ }
+
+ /**
+ * @return the resource key assigned to the given biome.
+ */
+ public static ResourceKey getKey(Biome biome) {
+ return BiomeRegistryImpl.getKey(biome);
+ }
+
+ /**
+ * @return the biome mapped to the given numerical ID.
+ */
+ public static Biome getBiome(int id) {
+ return BiomeRegistryImpl.getBiome(id);
+ }
+
+ /**
+ * @return the biome mapped to the given namespaced ID.
+ */
+ public static Biome getBiome(NamespacedIdentifier identifier) {
+ return BiomeRegistryImpl.getBiome(identifier);
+ }
+
+ /**
+ * @return the biome mapped to the given resource key.
+ */
+ public static Biome getBiome(ResourceKey key) {
+ return BiomeRegistryImpl.getBiome(key);
+ }
+
+ /**
+ * @return a set containing all namespaced IDs in the registry.
+ */
+ public static Set identifierSet() {
+ return BiomeRegistryImpl.identifierSet();
+ }
+
+ /**
+ * @return a set containing all resource keys in the registry.
+ */
+ public static Set> keySet() {
+ return BiomeRegistryImpl.keySet();
+ }
+
+ /**
+ * @param the biome type.
+ * @param identifier the namespaced ID of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ */
+ public static T register(NamespacedIdentifier identifier, T biome) {
+ return BiomeRegistryImpl.register(identifier, biome);
+ }
+
+ /**
+ * @param the biome type.
+ * @param key the resource key of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ */
+ public static T register(ResourceKey key, T biome) {
+ return BiomeRegistryImpl.register(key, biome);
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java
new file mode 100644
index 00000000..c572d390
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java
@@ -0,0 +1,14 @@
+package net.ornithemc.osl.biomes.api.biome;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+
+public interface BiomeExtension {
+
+ interface BuilderExtension {
+
+ Biome.Builder parent(NamespacedIdentifier identifier);
+
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/BiomeIdRegistry.java b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/BiomeIdRegistry.java
new file mode 100644
index 00000000..0ca2ddfc
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/BiomeIdRegistry.java
@@ -0,0 +1,20 @@
+package net.ornithemc.osl.biomes.impl;
+
+import net.minecraft.resource.Identifier;
+import net.minecraft.util.registry.IdRegistry;
+import net.minecraft.world.biome.Biome;
+
+/**
+ * The biome registry is created and populated in Biome's class initializer.
+ * This breaks OSL's usual pattern of registering the registry in the API entrypoint but
+ * triggering registry population during bootstrapping, since OSL has to wrap the Vanilla
+ * registry which is not possible without triggering Biome class load and registry
+ * population.
+ * The solution: move the Vanilla registry to another class and replace the IdRegistry
+ * reference in Biome with this one.
+ */
+public final class BiomeIdRegistry {
+
+ public static final IdRegistry REGISTRY = new IdRegistry<>();
+
+}
diff --git a/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java
new file mode 100644
index 00000000..c00d2e7d
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java
@@ -0,0 +1,99 @@
+package net.ornithemc.osl.biomes.impl;
+
+import java.util.Set;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.biomes.api.BiomeEvents;
+import net.ornithemc.osl.registries.api.registry.Registry;
+import net.ornithemc.osl.registries.api.registry.RegistryKeys;
+import net.ornithemc.osl.registries.api.registry.ResourceKey;
+import net.ornithemc.osl.registries.api.registry.SyncedRegistries;
+import net.ornithemc.osl.registries.impl.registry.VanillaRegistries;
+
+public final class BiomeRegistryImpl {
+
+ public static final Registry REGISTRY = VanillaRegistries.registerSimple(RegistryKeys.BIOME, BiomeIdRegistry.REGISTRY, () -> Biome.REGISTRY);
+
+ private static boolean locked = true;
+
+ public static int getId(Biome biome) {
+ return REGISTRY.getId(biome);
+ }
+
+ public static NamespacedIdentifier getIdentifier(Biome biome) {
+ return REGISTRY.getIdentifier(biome);
+ }
+
+ public static ResourceKey getKey(Biome biome) {
+ return REGISTRY.getKey(biome);
+ }
+
+ public static Biome getBiome(int id) {
+ return REGISTRY.get(id);
+ }
+
+ public static Biome getBiome(NamespacedIdentifier identifier) {
+ return REGISTRY.get(identifier);
+ }
+
+ public static Biome getBiome(ResourceKey key) {
+ return REGISTRY.get(key);
+ }
+
+ public static Set identifierSet() {
+ return REGISTRY.identifierSet();
+ }
+
+ public static Set> keySet() {
+ return REGISTRY.keySet();
+ }
+
+ public static T register(NamespacedIdentifier identifier, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ if (biome.isMutated()) {
+ registerBiomeMutation(identifier, biome);
+ }
+
+ return Registry.register(REGISTRY, identifier, biome);
+ }
+ }
+
+ public static T register(ResourceKey key, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ if (biome.isMutated()) {
+ registerBiomeMutation(key.identifier(), biome);
+ }
+
+ return Registry.register(REGISTRY, key, biome);
+ }
+ }
+
+ private static void registerBiomeMutation(NamespacedIdentifier identifier, Biome biome) {
+ NamespacedIdentifier parentIdentifier = biome.osl$biomes$getParentIdentifier();
+ Biome parent = REGISTRY.get(parentIdentifier);
+
+ if (parent == null) {
+ throw new IllegalStateException("Error registering mutated biome " + identifier + ": parent " + parentIdentifier + " does not exist!");
+ } else {
+ Biome.MUTATED_BIOMES.put(biome, REGISTRY.getId(parent));
+ }
+ }
+
+ public static void init() {
+ SyncedRegistries.register(RegistryKeys.BIOME);
+ }
+
+ public static void unlock() {
+ locked = false;
+ }
+
+ public static void registerBiomes() {
+ BiomeEvents.REGISTER_BIOMES.invoker().run();
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/access/BiomeAccess.java b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/access/BiomeAccess.java
new file mode 100644
index 00000000..e64d1669
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/access/BiomeAccess.java
@@ -0,0 +1,10 @@
+package net.ornithemc.osl.biomes.impl.access;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+
+public interface BiomeAccess {
+
+ default NamespacedIdentifier osl$biomes$getParentIdentifier() {
+ throw new AbstractMethodError();
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java
new file mode 100644
index 00000000..cf87b89b
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java
@@ -0,0 +1,17 @@
+package net.ornithemc.osl.biomes.impl.biome;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+
+public interface BiomeExtensionImpl extends BiomeExtension {
+
+ interface BuilderExtensionImpl extends BuilderExtension {
+
+ @Override
+ default Biome.Builder parent(NamespacedIdentifier identifier) {
+ throw new AbstractMethodError();
+ }
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeBuilderMixin.java b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeBuilderMixin.java
new file mode 100644
index 00000000..361f23f5
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeBuilderMixin.java
@@ -0,0 +1,22 @@
+package net.ornithemc.osl.biomes.impl.mixin.common;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+
+@Mixin(Biome.Builder.class)
+public class BiomeBuilderMixin implements BiomeExtension.BuilderExtension {
+
+ @Shadow
+ public String parent;
+
+ @Override
+ public Biome.Builder parent(NamespacedIdentifier identifier) {
+ this.parent = identifier.toString();
+ return (Biome.Builder) (Object) this;
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java
new file mode 100644
index 00000000..28719fef
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java
@@ -0,0 +1,74 @@
+package net.ornithemc.osl.biomes.impl.mixin.common;
+
+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.Inject;
+import org.spongepowered.asm.mixin.injection.Redirect;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import net.minecraft.resource.Identifier;
+import net.minecraft.util.Id2ObjectBiMap;
+import net.minecraft.util.registry.IdRegistry;
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+import net.ornithemc.osl.biomes.impl.BiomeIdRegistry;
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.biomes.impl.access.BiomeAccess;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
+import net.ornithemc.osl.registries.api.registry.RegistryKeys;
+import net.ornithemc.osl.registries.api.registry.SyncedRegistries;
+import net.ornithemc.osl.registries.api.registry.sync.Id2ObjectBiMapMapper;
+
+@Mixin(Biome.class)
+public class BiomeMixin implements BiomeExtension, BiomeAccess {
+
+ @Shadow @Final
+ public static Id2ObjectBiMap MUTATED_BIOMES;
+
+ @Shadow @Final
+ private String parent;
+
+ @Redirect(
+ method = "",
+ at = @At(
+ value = "NEW",
+ target = "net/minecraft/util/registry/IdRegistry"
+ )
+ )
+ private static IdRegistry osl$biomes$replaceIdRegistry() {
+ // this allows us to register the biome registry in
+ // the API entrypoint without triggering a Biome class load
+ return BiomeIdRegistry.REGISTRY;
+ }
+
+ @Inject(
+ method = "init",
+ at = @At(
+ value = "HEAD"
+ )
+ )
+ private static void osl$biomes$unlockBiomeRegistry(CallbackInfo ci) {
+ BiomeRegistryImpl.unlock();
+ }
+
+ @Inject(
+ method = "init",
+ at = @At(
+ value = "TAIL"
+ )
+ )
+ private static void osl$biomes$registerBiomesAndMappers(CallbackInfo ci) {
+ BiomeRegistryImpl.registerBiomes();
+
+ SyncedRegistries.registerMapper(RegistryKeys.BIOME, NamespacedIdentifiers.from("mutated_biome"), Id2ObjectBiMapMapper.of(MUTATED_BIOMES));
+ }
+
+ @Override
+ public NamespacedIdentifier osl$biomes$getParentIdentifier() {
+ return this.parent == null ? null : NamespacedIdentifiers.parse(this.parent);
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/resources/fabric.mod.json b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/resources/fabric.mod.json
new file mode 100644
index 00000000..cb8fe0bb
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/resources/fabric.mod.json
@@ -0,0 +1,38 @@
+{
+ "schemaVersion": 1,
+ "id": "osl-biomes",
+ "version": "0.1.0+mc18w06a-mc18w31a",
+ "environment": "*",
+ "entrypoints": {
+ "init": [
+ "net.ornithemc.osl.biomes.impl.BiomeRegistryImpl::init"
+ ]
+ },
+ "mixins": [
+ "osl.biomes.mixins.json"
+ ],
+ "accessWidener": "osl.biomes.classtweaker",
+ "depends": {
+ "fabricloader": "\u003e\u003d0.18.0",
+ "minecraft": "\u003e\u003d1.13-alpha.18.6.a \u003c\u003d1.13.1-alpha.18.31.a",
+ "osl-core": "\u003e\u003d0.9.0",
+ "osl-entrypoints": "\u003e\u003d0.5.0",
+ "osl-lifecycle-events": "\u003e\u003d0.6.0",
+ "osl-executors": "\u003e\u003d0.1.0",
+ "osl-text-components": "\u003e\u003d0.1.0-",
+ "osl-networking": "\u003e\u003d0.10.0",
+ "osl-networking-impl": "\u003e\u003d0.2.0",
+ "osl-registries": "\u003e\u003d0.1.0"
+ },
+ "name": "OSL Biomes",
+ "description": "Biomes API and events.",
+ "authors": [
+ "OrnitheMC"
+ ],
+ "contact": {
+ "homepage": "https://ornithemc.net/",
+ "issues": "https://github.com/OrnitheMC/ornithe-standard-libraries/issues",
+ "sources": "https://github.com/OrnitheMC/ornithe-standard-libraries"
+ },
+ "license": "Apache-2.0"
+}
\ No newline at end of file
diff --git a/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/resources/osl.biomes.classtweaker b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/resources/osl.biomes.classtweaker
new file mode 100644
index 00000000..b6382d78
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/resources/osl.biomes.classtweaker
@@ -0,0 +1,8 @@
+classTweaker v1 named
+
+transitive-accessible method net/minecraft/world/biome/Biome (Lnet/minecraft/world/biome/Biome$Builder;)V
+
+transitive-inject-interface net/minecraft/world/biome/Biome net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl
+transitive-inject-interface net/minecraft/world/biome/Biome$Builder net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl$BuilderExtensionImpl
+
+inject-interface net/minecraft/world/biome/Biome net/ornithemc/osl/biomes/impl/access/BiomeAccess
diff --git a/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/resources/osl.biomes.mixins.json b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/resources/osl.biomes.mixins.json
new file mode 100644
index 00000000..cb076b3f
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w06a-mc18w31a/src/main/resources/osl.biomes.mixins.json
@@ -0,0 +1,18 @@
+{
+ "required": true,
+ "minVersion": "0.8",
+ "package": "net.ornithemc.osl.biomes.impl.mixin",
+ "compatibilityLevel": "JAVA_8",
+ "plugin": "net.ornithemc.osl.biomes.impl.BiomesMixinPlugin",
+ "mixins": [
+ "common.BiomeMixin",
+ "common.BiomeBuilderMixin"
+ ],
+ "client": [
+ ],
+ "server": [
+ ],
+ "injectors": {
+ "defaultRequire": 1
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w32a-mc1.13.2/build.gradle b/libraries/biomes/biomes-mc18w32a-mc1.13.2/build.gradle
new file mode 100644
index 00000000..0a350fdb
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w32a-mc1.13.2/build.gradle
@@ -0,0 +1 @@
+setUpModule(project)
diff --git a/libraries/biomes/biomes-mc18w32a-mc1.13.2/gradle.properties b/libraries/biomes/biomes-mc18w32a-mc1.13.2/gradle.properties
new file mode 100644
index 00000000..1a4324ef
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w32a-mc1.13.2/gradle.properties
@@ -0,0 +1,4 @@
+min_mc_version = 18w32a
+max_mc_version = 1.13.2
+
+minecraft_version = 1.13.2
diff --git a/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java
new file mode 100644
index 00000000..0d49c6f2
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java
@@ -0,0 +1,34 @@
+package net.ornithemc.osl.biomes.api;
+
+import net.ornithemc.osl.core.api.events.Event;
+
+/**
+ * Events related to the biomes lifecycle.
+ */
+public final class BiomeEvents {
+
+ /**
+ * This event is invoked upon game start-up, after Vanilla biome registration is finished.
+ *
+ *
+ * Custom biome registration should be done in a listener of this event.
+ * Helper methods for registering biomes can be found in the {@linkplain
+ * BiomeRegistry} class.
+ *
+ *
+ * Listeners to this event should be registered in your mod's entrypoint,
+ * and can be done as follows:
+ *
+ *
+ * {@code
+ * BiomeEvents.REGISTER_BIOMES.register(() -> {
+ * BiomeRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new CookieBiome());
+ * });
+ * }
+ *
+ *
+ * @see BiomeRegistry
+ */
+ public static final Event REGISTER_BIOMES = Event.runnable();
+
+}
diff --git a/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java
new file mode 100644
index 00000000..bc8fb566
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java
@@ -0,0 +1,91 @@
+package net.ornithemc.osl.biomes.api;
+
+import java.util.Set;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.registries.api.registry.ResourceKey;
+
+/**
+ * Public access to the Biomes registry.
+ */
+public final class BiomeRegistry {
+
+ /**
+ * @return the numerical ID assigned to the given biome.
+ */
+ public static int getId(Biome biome) {
+ return BiomeRegistryImpl.getId(biome);
+ }
+
+ /**
+ * @return the namespaced ID assigned to the given biome.
+ */
+ public static NamespacedIdentifier getIdentifier(Biome biome) {
+ return BiomeRegistryImpl.getIdentifier(biome);
+ }
+
+ /**
+ * @return the resource key assigned to the given biome.
+ */
+ public static ResourceKey getKey(Biome biome) {
+ return BiomeRegistryImpl.getKey(biome);
+ }
+
+ /**
+ * @return the biome mapped to the given numerical ID.
+ */
+ public static Biome getBiome(int id) {
+ return BiomeRegistryImpl.getBiome(id);
+ }
+
+ /**
+ * @return the biome mapped to the given namespaced ID.
+ */
+ public static Biome getBiome(NamespacedIdentifier identifier) {
+ return BiomeRegistryImpl.getBiome(identifier);
+ }
+
+ /**
+ * @return the biome mapped to the given resource key.
+ */
+ public static Biome getBiome(ResourceKey key) {
+ return BiomeRegistryImpl.getBiome(key);
+ }
+
+ /**
+ * @return a set containing all namespaced IDs in the registry.
+ */
+ public static Set identifierSet() {
+ return BiomeRegistryImpl.identifierSet();
+ }
+
+ /**
+ * @return a set containing all resource keys in the registry.
+ */
+ public static Set> keySet() {
+ return BiomeRegistryImpl.keySet();
+ }
+
+ /**
+ * @param the biome type.
+ * @param identifier the namespaced ID of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ */
+ public static T register(NamespacedIdentifier identifier, T biome) {
+ return BiomeRegistryImpl.register(identifier, biome);
+ }
+
+ /**
+ * @param the biome type.
+ * @param key the resource key of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ */
+ public static T register(ResourceKey key, T biome) {
+ return BiomeRegistryImpl.register(key, biome);
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java
new file mode 100644
index 00000000..c572d390
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java
@@ -0,0 +1,14 @@
+package net.ornithemc.osl.biomes.api.biome;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+
+public interface BiomeExtension {
+
+ interface BuilderExtension {
+
+ Biome.Builder parent(NamespacedIdentifier identifier);
+
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java
new file mode 100644
index 00000000..43c96f8e
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java
@@ -0,0 +1,99 @@
+package net.ornithemc.osl.biomes.impl;
+
+import java.util.Set;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.biomes.api.BiomeEvents;
+import net.ornithemc.osl.registries.api.registry.Registry;
+import net.ornithemc.osl.registries.api.registry.RegistryKeys;
+import net.ornithemc.osl.registries.api.registry.ResourceKey;
+import net.ornithemc.osl.registries.api.registry.SyncedRegistries;
+import net.ornithemc.osl.registries.impl.registry.VanillaRegistries;
+
+public final class BiomeRegistryImpl {
+
+ public static final Registry REGISTRY = VanillaRegistries.registerSimple(RegistryKeys.BIOME, net.minecraft.util.registry.Registry.BIOME);
+
+ private static boolean locked = true;
+
+ public static int getId(Biome biome) {
+ return REGISTRY.getId(biome);
+ }
+
+ public static NamespacedIdentifier getIdentifier(Biome biome) {
+ return REGISTRY.getIdentifier(biome);
+ }
+
+ public static ResourceKey getKey(Biome biome) {
+ return REGISTRY.getKey(biome);
+ }
+
+ public static Biome getBiome(int id) {
+ return REGISTRY.get(id);
+ }
+
+ public static Biome getBiome(NamespacedIdentifier identifier) {
+ return REGISTRY.get(identifier);
+ }
+
+ public static Biome getBiome(ResourceKey key) {
+ return REGISTRY.get(key);
+ }
+
+ public static Set identifierSet() {
+ return REGISTRY.identifierSet();
+ }
+
+ public static Set> keySet() {
+ return REGISTRY.keySet();
+ }
+
+ public static T register(NamespacedIdentifier identifier, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ if (biome.isMutated()) {
+ registerBiomeMutation(identifier, biome);
+ }
+
+ return Registry.register(REGISTRY, identifier, biome);
+ }
+ }
+
+ public static T register(ResourceKey key, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ if (biome.isMutated()) {
+ registerBiomeMutation(key.identifier(), biome);
+ }
+
+ return Registry.register(REGISTRY, key, biome);
+ }
+ }
+
+ private static void registerBiomeMutation(NamespacedIdentifier identifier, Biome biome) {
+ NamespacedIdentifier parentIdentifier = biome.osl$biomes$getParentIdentifier();
+ Biome parent = REGISTRY.get(parentIdentifier);
+
+ if (parent == null) {
+ throw new IllegalStateException("Error registering mutated biome " + identifier + ": parent " + parentIdentifier + " does not exist!");
+ } else {
+ Biome.MUTATED_BIOMES.put(biome, REGISTRY.getId(parent));
+ }
+ }
+
+ public static void init() {
+ SyncedRegistries.register(RegistryKeys.BIOME);
+ }
+
+ public static void unlock() {
+ locked = false;
+ }
+
+ public static void registerBiomes() {
+ BiomeEvents.REGISTER_BIOMES.invoker().run();
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/impl/access/BiomeAccess.java b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/impl/access/BiomeAccess.java
new file mode 100644
index 00000000..e64d1669
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/impl/access/BiomeAccess.java
@@ -0,0 +1,10 @@
+package net.ornithemc.osl.biomes.impl.access;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+
+public interface BiomeAccess {
+
+ default NamespacedIdentifier osl$biomes$getParentIdentifier() {
+ throw new AbstractMethodError();
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java
new file mode 100644
index 00000000..cf87b89b
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java
@@ -0,0 +1,17 @@
+package net.ornithemc.osl.biomes.impl.biome;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+
+public interface BiomeExtensionImpl extends BiomeExtension {
+
+ interface BuilderExtensionImpl extends BuilderExtension {
+
+ @Override
+ default Biome.Builder parent(NamespacedIdentifier identifier) {
+ throw new AbstractMethodError();
+ }
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeBuilderMixin.java b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeBuilderMixin.java
new file mode 100644
index 00000000..361f23f5
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeBuilderMixin.java
@@ -0,0 +1,22 @@
+package net.ornithemc.osl.biomes.impl.mixin.common;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+
+@Mixin(Biome.Builder.class)
+public class BiomeBuilderMixin implements BiomeExtension.BuilderExtension {
+
+ @Shadow
+ public String parent;
+
+ @Override
+ public Biome.Builder parent(NamespacedIdentifier identifier) {
+ this.parent = identifier.toString();
+ return (Biome.Builder) (Object) this;
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java
new file mode 100644
index 00000000..870452c6
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java
@@ -0,0 +1,57 @@
+package net.ornithemc.osl.biomes.impl.mixin.common;
+
+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.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import net.minecraft.util.Id2ObjectBiMap;
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.biomes.impl.access.BiomeAccess;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
+import net.ornithemc.osl.registries.api.registry.RegistryKeys;
+import net.ornithemc.osl.registries.api.registry.SyncedRegistries;
+import net.ornithemc.osl.registries.api.registry.sync.Id2ObjectBiMapMapper;
+
+@Mixin(Biome.class)
+public class BiomeMixin implements BiomeExtension, BiomeAccess {
+
+ @Shadow @Final
+ public static Id2ObjectBiMap MUTATED_BIOMES;
+
+ @Shadow @Final
+ private String parent;
+
+ @Inject(
+ method = "init",
+ at = @At(
+ value = "HEAD"
+ )
+ )
+ private static void osl$biomes$unlockBiomeRegistry(CallbackInfo ci) {
+ BiomeRegistryImpl.unlock();
+ }
+
+ @Inject(
+ method = "init",
+ at = @At(
+ value = "TAIL"
+ )
+ )
+ private static void osl$biomes$registerBiomesAndMappers(CallbackInfo ci) {
+ BiomeRegistryImpl.registerBiomes();
+
+ SyncedRegistries.registerMapper(RegistryKeys.BIOME, NamespacedIdentifiers.from("mutated_biome"), Id2ObjectBiMapMapper.of(MUTATED_BIOMES));
+ }
+
+ @Override
+ public NamespacedIdentifier osl$biomes$getParentIdentifier() {
+ return this.parent == null ? null : NamespacedIdentifiers.parse(this.parent);
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json
new file mode 100644
index 00000000..214e2bc5
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json
@@ -0,0 +1,38 @@
+{
+ "schemaVersion": 1,
+ "id": "osl-biomes",
+ "version": "0.1.0+mc18w32a-mc1.13.2",
+ "environment": "*",
+ "entrypoints": {
+ "init": [
+ "net.ornithemc.osl.biomes.impl.BiomeRegistryImpl::init"
+ ]
+ },
+ "mixins": [
+ "osl.biomes.mixins.json"
+ ],
+ "accessWidener": "osl.biomes.classtweaker",
+ "depends": {
+ "fabricloader": "\u003e\u003d0.18.0",
+ "minecraft": "\u003e\u003d1.13.1-alpha.18.32.a \u003c\u003d1.13.2",
+ "osl-core": "\u003e\u003d0.9.0",
+ "osl-entrypoints": "\u003e\u003d0.5.0",
+ "osl-lifecycle-events": "\u003e\u003d0.6.0",
+ "osl-executors": "\u003e\u003d0.1.0",
+ "osl-text-components": "\u003e\u003d0.1.0-",
+ "osl-networking": "\u003e\u003d0.10.0",
+ "osl-networking-impl": "\u003e\u003d0.2.0",
+ "osl-registries": "\u003e\u003d0.1.0"
+ },
+ "name": "OSL Biomes",
+ "description": "Biomes API and events.",
+ "authors": [
+ "OrnitheMC"
+ ],
+ "contact": {
+ "homepage": "https://ornithemc.net/",
+ "issues": "https://github.com/OrnitheMC/ornithe-standard-libraries/issues",
+ "sources": "https://github.com/OrnitheMC/ornithe-standard-libraries"
+ },
+ "license": "Apache-2.0"
+}
\ No newline at end of file
diff --git a/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/resources/osl.biomes.classtweaker b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/resources/osl.biomes.classtweaker
new file mode 100644
index 00000000..b6382d78
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/resources/osl.biomes.classtweaker
@@ -0,0 +1,8 @@
+classTweaker v1 named
+
+transitive-accessible method net/minecraft/world/biome/Biome (Lnet/minecraft/world/biome/Biome$Builder;)V
+
+transitive-inject-interface net/minecraft/world/biome/Biome net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl
+transitive-inject-interface net/minecraft/world/biome/Biome$Builder net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl$BuilderExtensionImpl
+
+inject-interface net/minecraft/world/biome/Biome net/ornithemc/osl/biomes/impl/access/BiomeAccess
diff --git a/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/resources/osl.biomes.mixins.json b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/resources/osl.biomes.mixins.json
new file mode 100644
index 00000000..cb076b3f
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w32a-mc1.13.2/src/main/resources/osl.biomes.mixins.json
@@ -0,0 +1,18 @@
+{
+ "required": true,
+ "minVersion": "0.8",
+ "package": "net.ornithemc.osl.biomes.impl.mixin",
+ "compatibilityLevel": "JAVA_8",
+ "plugin": "net.ornithemc.osl.biomes.impl.BiomesMixinPlugin",
+ "mixins": [
+ "common.BiomeMixin",
+ "common.BiomeBuilderMixin"
+ ],
+ "client": [
+ ],
+ "server": [
+ ],
+ "injectors": {
+ "defaultRequire": 1
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w43a-mc1.14.4/build.gradle b/libraries/biomes/biomes-mc18w43a-mc1.14.4/build.gradle
new file mode 100644
index 00000000..0a350fdb
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w43a-mc1.14.4/build.gradle
@@ -0,0 +1 @@
+setUpModule(project)
diff --git a/libraries/biomes/biomes-mc18w43a-mc1.14.4/gradle.properties b/libraries/biomes/biomes-mc18w43a-mc1.14.4/gradle.properties
new file mode 100644
index 00000000..54620cac
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w43a-mc1.14.4/gradle.properties
@@ -0,0 +1,4 @@
+min_mc_version = 18w43a
+max_mc_version = 1.14.4
+
+minecraft_version = 1.14.4
diff --git a/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java
new file mode 100644
index 00000000..0d49c6f2
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java
@@ -0,0 +1,34 @@
+package net.ornithemc.osl.biomes.api;
+
+import net.ornithemc.osl.core.api.events.Event;
+
+/**
+ * Events related to the biomes lifecycle.
+ */
+public final class BiomeEvents {
+
+ /**
+ * This event is invoked upon game start-up, after Vanilla biome registration is finished.
+ *
+ *
+ * Custom biome registration should be done in a listener of this event.
+ * Helper methods for registering biomes can be found in the {@linkplain
+ * BiomeRegistry} class.
+ *
+ *
+ * Listeners to this event should be registered in your mod's entrypoint,
+ * and can be done as follows:
+ *
+ *
+ * {@code
+ * BiomeEvents.REGISTER_BIOMES.register(() -> {
+ * BiomeRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new CookieBiome());
+ * });
+ * }
+ *
+ *
+ * @see BiomeRegistry
+ */
+ public static final Event REGISTER_BIOMES = Event.runnable();
+
+}
diff --git a/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java
new file mode 100644
index 00000000..bc8fb566
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java
@@ -0,0 +1,91 @@
+package net.ornithemc.osl.biomes.api;
+
+import java.util.Set;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.registries.api.registry.ResourceKey;
+
+/**
+ * Public access to the Biomes registry.
+ */
+public final class BiomeRegistry {
+
+ /**
+ * @return the numerical ID assigned to the given biome.
+ */
+ public static int getId(Biome biome) {
+ return BiomeRegistryImpl.getId(biome);
+ }
+
+ /**
+ * @return the namespaced ID assigned to the given biome.
+ */
+ public static NamespacedIdentifier getIdentifier(Biome biome) {
+ return BiomeRegistryImpl.getIdentifier(biome);
+ }
+
+ /**
+ * @return the resource key assigned to the given biome.
+ */
+ public static ResourceKey getKey(Biome biome) {
+ return BiomeRegistryImpl.getKey(biome);
+ }
+
+ /**
+ * @return the biome mapped to the given numerical ID.
+ */
+ public static Biome getBiome(int id) {
+ return BiomeRegistryImpl.getBiome(id);
+ }
+
+ /**
+ * @return the biome mapped to the given namespaced ID.
+ */
+ public static Biome getBiome(NamespacedIdentifier identifier) {
+ return BiomeRegistryImpl.getBiome(identifier);
+ }
+
+ /**
+ * @return the biome mapped to the given resource key.
+ */
+ public static Biome getBiome(ResourceKey key) {
+ return BiomeRegistryImpl.getBiome(key);
+ }
+
+ /**
+ * @return a set containing all namespaced IDs in the registry.
+ */
+ public static Set identifierSet() {
+ return BiomeRegistryImpl.identifierSet();
+ }
+
+ /**
+ * @return a set containing all resource keys in the registry.
+ */
+ public static Set> keySet() {
+ return BiomeRegistryImpl.keySet();
+ }
+
+ /**
+ * @param the biome type.
+ * @param identifier the namespaced ID of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ */
+ public static T register(NamespacedIdentifier identifier, T biome) {
+ return BiomeRegistryImpl.register(identifier, biome);
+ }
+
+ /**
+ * @param the biome type.
+ * @param key the resource key of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ */
+ public static T register(ResourceKey key, T biome) {
+ return BiomeRegistryImpl.register(key, biome);
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java
new file mode 100644
index 00000000..c572d390
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java
@@ -0,0 +1,14 @@
+package net.ornithemc.osl.biomes.api.biome;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+
+public interface BiomeExtension {
+
+ interface BuilderExtension {
+
+ Biome.Builder parent(NamespacedIdentifier identifier);
+
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java
new file mode 100644
index 00000000..43c96f8e
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java
@@ -0,0 +1,99 @@
+package net.ornithemc.osl.biomes.impl;
+
+import java.util.Set;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.biomes.api.BiomeEvents;
+import net.ornithemc.osl.registries.api.registry.Registry;
+import net.ornithemc.osl.registries.api.registry.RegistryKeys;
+import net.ornithemc.osl.registries.api.registry.ResourceKey;
+import net.ornithemc.osl.registries.api.registry.SyncedRegistries;
+import net.ornithemc.osl.registries.impl.registry.VanillaRegistries;
+
+public final class BiomeRegistryImpl {
+
+ public static final Registry REGISTRY = VanillaRegistries.registerSimple(RegistryKeys.BIOME, net.minecraft.util.registry.Registry.BIOME);
+
+ private static boolean locked = true;
+
+ public static int getId(Biome biome) {
+ return REGISTRY.getId(biome);
+ }
+
+ public static NamespacedIdentifier getIdentifier(Biome biome) {
+ return REGISTRY.getIdentifier(biome);
+ }
+
+ public static ResourceKey getKey(Biome biome) {
+ return REGISTRY.getKey(biome);
+ }
+
+ public static Biome getBiome(int id) {
+ return REGISTRY.get(id);
+ }
+
+ public static Biome getBiome(NamespacedIdentifier identifier) {
+ return REGISTRY.get(identifier);
+ }
+
+ public static Biome getBiome(ResourceKey key) {
+ return REGISTRY.get(key);
+ }
+
+ public static Set identifierSet() {
+ return REGISTRY.identifierSet();
+ }
+
+ public static Set> keySet() {
+ return REGISTRY.keySet();
+ }
+
+ public static T register(NamespacedIdentifier identifier, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ if (biome.isMutated()) {
+ registerBiomeMutation(identifier, biome);
+ }
+
+ return Registry.register(REGISTRY, identifier, biome);
+ }
+ }
+
+ public static T register(ResourceKey key, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ if (biome.isMutated()) {
+ registerBiomeMutation(key.identifier(), biome);
+ }
+
+ return Registry.register(REGISTRY, key, biome);
+ }
+ }
+
+ private static void registerBiomeMutation(NamespacedIdentifier identifier, Biome biome) {
+ NamespacedIdentifier parentIdentifier = biome.osl$biomes$getParentIdentifier();
+ Biome parent = REGISTRY.get(parentIdentifier);
+
+ if (parent == null) {
+ throw new IllegalStateException("Error registering mutated biome " + identifier + ": parent " + parentIdentifier + " does not exist!");
+ } else {
+ Biome.MUTATED_BIOMES.put(biome, REGISTRY.getId(parent));
+ }
+ }
+
+ public static void init() {
+ SyncedRegistries.register(RegistryKeys.BIOME);
+ }
+
+ public static void unlock() {
+ locked = false;
+ }
+
+ public static void registerBiomes() {
+ BiomeEvents.REGISTER_BIOMES.invoker().run();
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/access/BiomeAccess.java b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/access/BiomeAccess.java
new file mode 100644
index 00000000..e64d1669
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/access/BiomeAccess.java
@@ -0,0 +1,10 @@
+package net.ornithemc.osl.biomes.impl.access;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+
+public interface BiomeAccess {
+
+ default NamespacedIdentifier osl$biomes$getParentIdentifier() {
+ throw new AbstractMethodError();
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java
new file mode 100644
index 00000000..cf87b89b
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java
@@ -0,0 +1,17 @@
+package net.ornithemc.osl.biomes.impl.biome;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+
+public interface BiomeExtensionImpl extends BiomeExtension {
+
+ interface BuilderExtensionImpl extends BuilderExtension {
+
+ @Override
+ default Biome.Builder parent(NamespacedIdentifier identifier) {
+ throw new AbstractMethodError();
+ }
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeBuilderMixin.java b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeBuilderMixin.java
new file mode 100644
index 00000000..361f23f5
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeBuilderMixin.java
@@ -0,0 +1,22 @@
+package net.ornithemc.osl.biomes.impl.mixin.common;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+
+@Mixin(Biome.Builder.class)
+public class BiomeBuilderMixin implements BiomeExtension.BuilderExtension {
+
+ @Shadow
+ public String parent;
+
+ @Override
+ public Biome.Builder parent(NamespacedIdentifier identifier) {
+ this.parent = identifier.toString();
+ return (Biome.Builder) (Object) this;
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java
new file mode 100644
index 00000000..530423b2
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java
@@ -0,0 +1,24 @@
+package net.ornithemc.osl.biomes.impl.mixin.common;
+
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+import net.ornithemc.osl.biomes.impl.access.BiomeAccess;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
+
+@Mixin(Biome.class)
+public class BiomeMixin implements BiomeExtension, BiomeAccess {
+
+ @Shadow @Final
+ private String parent;
+
+ @Override
+ public NamespacedIdentifier osl$biomes$getParentIdentifier() {
+ return this.parent == null ? null : NamespacedIdentifiers.parse(this.parent);
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomesMixin.java b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomesMixin.java
new file mode 100644
index 00000000..df2b51cc
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomesMixin.java
@@ -0,0 +1,41 @@
+package net.ornithemc.osl.biomes.impl.mixin.common;
+
+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;
+
+import net.minecraft.world.biome.Biome;
+import net.minecraft.world.biome.Biomes;
+
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
+import net.ornithemc.osl.registries.api.registry.RegistryKeys;
+import net.ornithemc.osl.registries.api.registry.SyncedRegistries;
+import net.ornithemc.osl.registries.api.registry.sync.Id2ObjectBiMapMapper;
+
+@Mixin(Biomes.class)
+public class BiomesMixin {
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "HEAD"
+ )
+ )
+ private static void osl$biomes$unlockBiomeRegistry(CallbackInfo ci) {
+ BiomeRegistryImpl.unlock();
+ }
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "TAIL"
+ )
+ )
+ private static void osl$biomes$registerBiomesAndMappers(CallbackInfo ci) {
+ BiomeRegistryImpl.registerBiomes();
+
+ SyncedRegistries.registerMapper(RegistryKeys.BIOME, NamespacedIdentifiers.from("mutated_biome"), Id2ObjectBiMapMapper.of(Biome.MUTATED_BIOMES));
+ }
+}
diff --git a/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json
new file mode 100644
index 00000000..b90aa8f4
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json
@@ -0,0 +1,38 @@
+{
+ "schemaVersion": 1,
+ "id": "osl-biomes",
+ "version": "0.1.0+mc18w43a-mc1.14.4",
+ "environment": "*",
+ "entrypoints": {
+ "init": [
+ "net.ornithemc.osl.biomes.impl.BiomeRegistryImpl::init"
+ ]
+ },
+ "mixins": [
+ "osl.biomes.mixins.json"
+ ],
+ "accessWidener": "osl.biomes.classtweaker",
+ "depends": {
+ "fabricloader": "\u003e\u003d0.18.0",
+ "minecraft": "\u003e\u003d1.14-alpha.18.43.a \u003c\u003d1.14.4",
+ "osl-core": "\u003e\u003d0.9.0",
+ "osl-entrypoints": "\u003e\u003d0.5.0",
+ "osl-lifecycle-events": "\u003e\u003d0.6.0",
+ "osl-executors": "\u003e\u003d0.1.0",
+ "osl-text-components": "\u003e\u003d0.1.0-",
+ "osl-networking": "\u003e\u003d0.10.0",
+ "osl-networking-impl": "\u003e\u003d0.2.0",
+ "osl-registries": "\u003e\u003d0.1.0"
+ },
+ "name": "OSL Biomes",
+ "description": "Biomes API and events.",
+ "authors": [
+ "OrnitheMC"
+ ],
+ "contact": {
+ "homepage": "https://ornithemc.net/",
+ "issues": "https://github.com/OrnitheMC/ornithe-standard-libraries/issues",
+ "sources": "https://github.com/OrnitheMC/ornithe-standard-libraries"
+ },
+ "license": "Apache-2.0"
+}
\ No newline at end of file
diff --git a/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/resources/osl.biomes.classtweaker b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/resources/osl.biomes.classtweaker
new file mode 100644
index 00000000..b6382d78
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/resources/osl.biomes.classtweaker
@@ -0,0 +1,8 @@
+classTweaker v1 named
+
+transitive-accessible method net/minecraft/world/biome/Biome (Lnet/minecraft/world/biome/Biome$Builder;)V
+
+transitive-inject-interface net/minecraft/world/biome/Biome net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl
+transitive-inject-interface net/minecraft/world/biome/Biome$Builder net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl$BuilderExtensionImpl
+
+inject-interface net/minecraft/world/biome/Biome net/ornithemc/osl/biomes/impl/access/BiomeAccess
diff --git a/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/resources/osl.biomes.mixins.json b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/resources/osl.biomes.mixins.json
new file mode 100644
index 00000000..05d122c2
--- /dev/null
+++ b/libraries/biomes/biomes-mc18w43a-mc1.14.4/src/main/resources/osl.biomes.mixins.json
@@ -0,0 +1,19 @@
+{
+ "required": true,
+ "minVersion": "0.8",
+ "package": "net.ornithemc.osl.biomes.impl.mixin",
+ "compatibilityLevel": "JAVA_8",
+ "plugin": "net.ornithemc.osl.biomes.impl.BiomesMixinPlugin",
+ "mixins": [
+ "common.BiomeMixin",
+ "common.BiomesMixin",
+ "common.BiomeBuilderMixin"
+ ],
+ "client": [
+ ],
+ "server": [
+ ],
+ "injectors": {
+ "defaultRequire": 1
+ }
+}
diff --git a/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/build.gradle b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/build.gradle
new file mode 100644
index 00000000..0a350fdb
--- /dev/null
+++ b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/build.gradle
@@ -0,0 +1 @@
+setUpModule(project)
diff --git a/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/gradle.properties b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/gradle.properties
new file mode 100644
index 00000000..c2b9c874
--- /dev/null
+++ b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/gradle.properties
@@ -0,0 +1,7 @@
+min_mc_version = b1.8-pre1
+max_mc_version = 1.6.4
+
+minecraft_version = 1.6.4
+raven_build = 1
+sparrow_build = 1
+nests_build = 3
diff --git a/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java
new file mode 100644
index 00000000..0d49c6f2
--- /dev/null
+++ b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/api/BiomeEvents.java
@@ -0,0 +1,34 @@
+package net.ornithemc.osl.biomes.api;
+
+import net.ornithemc.osl.core.api.events.Event;
+
+/**
+ * Events related to the biomes lifecycle.
+ */
+public final class BiomeEvents {
+
+ /**
+ * This event is invoked upon game start-up, after Vanilla biome registration is finished.
+ *
+ *
+ * Custom biome registration should be done in a listener of this event.
+ * Helper methods for registering biomes can be found in the {@linkplain
+ * BiomeRegistry} class.
+ *
+ *
+ * Listeners to this event should be registered in your mod's entrypoint,
+ * and can be done as follows:
+ *
+ *
+ * {@code
+ * BiomeEvents.REGISTER_BIOMES.register(() -> {
+ * BiomeRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new CookieBiome());
+ * });
+ * }
+ *
+ *
+ * @see BiomeRegistry
+ */
+ public static final Event REGISTER_BIOMES = Event.runnable();
+
+}
diff --git a/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java
new file mode 100644
index 00000000..86e85031
--- /dev/null
+++ b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/api/BiomeRegistry.java
@@ -0,0 +1,106 @@
+package net.ornithemc.osl.biomes.api;
+
+import java.util.Set;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.registries.api.registry.ResourceKey;
+
+/**
+ * Public access to the Biomes registry.
+ */
+public final class BiomeRegistry {
+
+ /**
+ * @return the numerical ID assigned to the given biome.
+ */
+ public static int getId(Biome biome) {
+ return BiomeRegistryImpl.getId(biome);
+ }
+
+ /**
+ * @return the namespaced ID assigned to the given biome.
+ */
+ public static NamespacedIdentifier getIdentifier(Biome biome) {
+ return BiomeRegistryImpl.getIdentifier(biome);
+ }
+
+ /**
+ * @return the resource key assigned to the given biome.
+ */
+ public static ResourceKey getKey(Biome biome) {
+ return BiomeRegistryImpl.getKey(biome);
+ }
+
+ /**
+ * @return the biome mapped to the given numerical ID.
+ */
+ public static Biome getBiome(int id) {
+ return BiomeRegistryImpl.getBiome(id);
+ }
+
+ /**
+ * @return the biome mapped to the given namespaced ID.
+ */
+ public static Biome getBiome(NamespacedIdentifier identifier) {
+ return BiomeRegistryImpl.getBiome(identifier);
+ }
+
+ /**
+ * @return the biome mapped to the given resource key.
+ */
+ public static Biome getBiome(ResourceKey key) {
+ return BiomeRegistryImpl.getBiome(key);
+ }
+
+ /**
+ * @return a set containing all namespaced IDs in the registry.
+ */
+ public static Set identifierSet() {
+ return BiomeRegistryImpl.identifierSet();
+ }
+
+ /**
+ * @return a set containing all resource keys in the registry.
+ */
+ public static Set> keySet() {
+ return BiomeRegistryImpl.keySet();
+ }
+
+ /**
+ * @param the biome type.
+ * @param identifier the namespaced ID of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ */
+ public static T register(NamespacedIdentifier identifier, T biome) {
+ return BiomeRegistryImpl.register(identifier, biome);
+ }
+
+ /**
+ * @param the biome type.
+ * @param key the resource key of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ */
+ public static T register(ResourceKey key, T biome) {
+ return BiomeRegistryImpl.register(key, biome);
+ }
+
+ /**
+ * @param the biome type.
+ * @param id the numerical ID of the biome.
+ * @param key the namespaced ID of the biome.
+ * @param biome the biome to register.
+ * @return the registered biome.
+ *
+ * @deprecated use {@linkplain #register(NamespacedIdentifier, Biome)}
+ * or {@linkplain #register(ResourceKey, Biome)} instead.
+ */
+ @Deprecated
+ public static T register(int id, NamespacedIdentifier key, T biome) {
+ return BiomeRegistryImpl.register(id, key, biome);
+ }
+}
diff --git a/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java
new file mode 100644
index 00000000..06d6a59b
--- /dev/null
+++ b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/api/biome/BiomeExtension.java
@@ -0,0 +1,13 @@
+package net.ornithemc.osl.biomes.api.biome;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.registries.api.registry.Registry;
+
+public interface BiomeExtension {
+
+ Registry REGISTRY = BiomeRegistryImpl.REGISTRY;
+ int AUTO_ASSIGN_ID = -172;
+
+}
diff --git a/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java
new file mode 100644
index 00000000..46583dba
--- /dev/null
+++ b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/BiomeRegistryImpl.java
@@ -0,0 +1,111 @@
+package net.ornithemc.osl.biomes.impl;
+
+import java.util.Set;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
+import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
+import net.ornithemc.osl.biomes.api.BiomeEvents;
+import net.ornithemc.osl.biomes.impl.biome.BiomeIdFixer;
+import net.ornithemc.osl.registries.api.registry.Registries;
+import net.ornithemc.osl.registries.api.registry.Registry;
+import net.ornithemc.osl.registries.api.registry.RegistryKeys;
+import net.ornithemc.osl.registries.api.registry.ResourceKey;
+import net.ornithemc.osl.registries.api.registry.SyncedRegistries;
+import net.ornithemc.osl.registries.impl.registry.RegistriesImpl;
+
+public final class BiomeRegistryImpl {
+
+ public static final Registry REGISTRY = Registries.registerSimple(RegistryKeys.BIOME, () -> Biome.BY_ID.getClass());
+
+ private static boolean locked = true;
+
+ public static int getId(Biome biome) {
+ return REGISTRY.getId(biome);
+ }
+
+ public static NamespacedIdentifier getIdentifier(Biome biome) {
+ return REGISTRY.getIdentifier(biome);
+ }
+
+ public static ResourceKey getKey(Biome biome) {
+ return REGISTRY.getKey(biome);
+ }
+
+ public static Biome getBiome(int id) {
+ return REGISTRY.get(id);
+ }
+
+ public static Biome getBiome(NamespacedIdentifier identifier) {
+ return REGISTRY.get(identifier);
+ }
+
+ public static Biome getBiome(ResourceKey key) {
+ return REGISTRY.get(key);
+ }
+
+ public static Set identifierSet() {
+ return REGISTRY.identifierSet();
+ }
+
+ public static Set> keySet() {
+ return REGISTRY.keySet();
+ }
+
+ @SuppressWarnings("deprecation")
+ public static T register(NamespacedIdentifier identifier, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ return Registry.register(REGISTRY, biome.id, identifier, biome);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public static T register(ResourceKey key, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ return Registry.register(REGISTRY, biome.id, key, biome);
+ }
+ }
+
+ @Deprecated
+ public static T register(int id, NamespacedIdentifier key, T biome) {
+ if (locked) {
+ throw new IllegalStateException("register called too early: registry locked!");
+ } else {
+ if (biome.id != id) {
+ throw new IllegalArgumentException("ID " + id + " does not match biome ID " + biome.id + " for " + key);
+ }
+
+ return Registry.register(REGISTRY, id, key, biome);
+ }
+ }
+
+ public static void init() {
+ SyncedRegistries.register(RegistryKeys.BIOME);
+ SyncedRegistries.registerFixer(RegistryKeys.BIOME, NamespacedIdentifiers.from("biome/id"), new BiomeIdFixer());
+ }
+
+ public static void unlock() {
+ locked = false;
+ }
+
+ public static void registerBiomes() {
+ VanillaBiomes.init();
+ BiomeEvents.REGISTER_BIOMES.invoker().run();
+ }
+
+ public static void registerUnknownBiomes() {
+ for (Biome biome : Biome.BY_ID) {
+ if (biome != null && REGISTRY.getIdentifier(biome) == null) {
+ NamespacedIdentifier identifier = NamespacedIdentifiers.from("osl", "biome_" + biome.id);
+
+ RegistriesImpl.LOGGER.warn("Biome {}/{}", biome.id, biome.getClass().getSimpleName() + " was not registered to OSL's Biome registry! Adding it as '" + identifier + "'...");
+ BiomeRegistryImpl.register(identifier, biome);
+ }
+ }
+ }
+}
diff --git a/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/BiomesMixinPlugin.java b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/BiomesMixinPlugin.java
new file mode 100644
index 00000000..e52a2ca8
--- /dev/null
+++ b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/BiomesMixinPlugin.java
@@ -0,0 +1,45 @@
+package net.ornithemc.osl.biomes.impl;
+
+import java.util.List;
+import java.util.Set;
+
+import org.objectweb.asm.tree.ClassNode;
+
+import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
+import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
+
+public class BiomesMixinPlugin implements IMixinConfigPlugin {
+
+ public static final boolean BIOME_IDS_BEYOND_255_SUPPORTED = false;
+
+ @Override
+ public void onLoad(String mixinPackage) {
+ }
+
+ @Override
+ public String getRefMapperConfig() {
+ return null;
+ }
+
+ @Override
+ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
+ return true;
+ }
+
+ @Override
+ public void acceptTargets(Set myTargets, Set otherTargets) {
+ }
+
+ @Override
+ public List getMixins() {
+ return null;
+ }
+
+ @Override
+ public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
+ }
+
+ @Override
+ public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
+ }
+}
diff --git a/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/VanillaBiomes.java b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/VanillaBiomes.java
new file mode 100644
index 00000000..f8b11ddf
--- /dev/null
+++ b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/VanillaBiomes.java
@@ -0,0 +1,73 @@
+package net.ornithemc.osl.biomes.impl;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
+
+public final class VanillaBiomes {
+
+ /**
+ * Namespaced IDs were introduced in 1.9. Before then, the numerical IDs
+ * were the only unique identifiers for biomes. Here we assign namespaced
+ * IDs to pre-1.7 biomes, matching the 1.9 IDs where possible.
+ */
+ private static final String[] IDENTIFIERS = {
+ // grouped per 10 for easier lookup
+
+ "ocean",
+ "plains",
+ "desert",
+ "extreme_hills",
+ "forest",
+ "taiga",
+ "swampland",
+ "river",
+ "hell",
+ "sky",
+
+ "frozen_ocean",
+ "frozen_river",
+ "ice_flats",
+ "ice_mountains",
+ "mushroom_island",
+ "mushroom_island_shore",
+ "beaches",
+ "desert_hills",
+ "forest_hills",
+ "taiga_hills",
+
+ "smaller_extreme_hills",
+ "jungle",
+ "jungle_hills"
+ };
+
+ public static final int MAX_ID = 255;
+
+ static void init() {
+ for (Field f : Biome.class.getDeclaredFields()) {
+ if (Modifier.isStatic(f.getModifiers()) && Biome.class.isAssignableFrom(f.getType())) {
+ try {
+ Biome biome = (Biome) f.get(null);
+
+ if (biome != null) {
+ register(biome);
+ }
+ } catch (Throwable t) {
+ }
+ }
+ }
+ }
+
+ private static void register(Biome biome) {
+ if (biome.id >= 0 && biome.id < IDENTIFIERS.length) {
+ String identifier = IDENTIFIERS[biome.id];
+
+ if (identifier != null) {
+ BiomeRegistryImpl.register(NamespacedIdentifiers.from(identifier), biome);
+ }
+ }
+ }
+}
diff --git a/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java
new file mode 100644
index 00000000..1b77c6af
--- /dev/null
+++ b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl.java
@@ -0,0 +1,6 @@
+package net.ornithemc.osl.biomes.impl.biome;
+
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+
+public interface BiomeExtensionImpl extends BiomeExtension {
+}
diff --git a/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeIdFixer.java b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeIdFixer.java
new file mode 100644
index 00000000..1bacf15f
--- /dev/null
+++ b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/biome/BiomeIdFixer.java
@@ -0,0 +1,19 @@
+package net.ornithemc.osl.biomes.impl.biome;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.registries.api.registry.sync.IdFixer;
+
+public class BiomeIdFixer implements IdFixer {
+
+ @Override
+ public void apply() {
+ for (int id = 0; id < Biome.BY_ID.length; id++) {
+ Biome biome = Biome.BY_ID[id];
+
+ if (biome != null) {
+ biome.id = id;
+ }
+ }
+ }
+}
diff --git a/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java
new file mode 100644
index 00000000..763a08c6
--- /dev/null
+++ b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/java/net/ornithemc/osl/biomes/impl/mixin/common/BiomeMixin.java
@@ -0,0 +1,101 @@
+package net.ornithemc.osl.biomes.impl.mixin.common;
+
+import org.objectweb.asm.Opcodes;
+
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Mutable;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.At.Shift;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.ModifyVariable;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import net.minecraft.world.biome.Biome;
+
+import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
+import net.ornithemc.osl.biomes.api.biome.BiomeExtension;
+import net.ornithemc.osl.biomes.impl.BiomeRegistryImpl;
+import net.ornithemc.osl.biomes.impl.BiomesMixinPlugin;
+import net.ornithemc.osl.biomes.impl.VanillaBiomes;
+import net.ornithemc.osl.registries.api.registry.RegistryKeys;
+import net.ornithemc.osl.registries.api.registry.SyncedRegistries;
+import net.ornithemc.osl.registries.api.registry.sync.ArrayMapper;
+import net.ornithemc.osl.registries.api.registry.sync.DynamicArray;
+
+@Mixin(Biome.class)
+public class BiomeMixin implements BiomeExtension {
+
+ @Shadow @Final @Mutable
+ private static Biome[] BY_ID;
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "HEAD"
+ )
+ )
+ private static void osl$biomes$unlockBiomeRegistry(CallbackInfo ci) {
+ BiomeRegistryImpl.unlock();
+ }
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "TAIL"
+ )
+ )
+ private static void osl$biomes$registerBiomesAndArrayMappers(CallbackInfo ci) {
+ BiomeRegistryImpl.registerBiomes();
+ BiomeRegistryImpl.registerUnknownBiomes();
+
+ SyncedRegistries.registerMapper(RegistryKeys.BIOME, NamespacedIdentifiers.from("biome/by_id"), ArrayMapper.of(() -> BY_ID, a -> BY_ID = a));
+ }
+
+ @ModifyVariable(
+ method = "",
+ argsOnly = true,
+ ordinal = 0,
+ at = @At(
+ value = "INVOKE",
+ target = "Ljava/lang/Object;()V",
+ shift = Shift.AFTER
+ )
+ )
+ private int osl$biomes$handleAutoAssignId(int id) {
+ if (id == AUTO_ASSIGN_ID) {
+ // the Biome[] array must contain all biomes so this should
+ // give us a valid ID for the Biome registry to use.
+ id = DynamicArray.length(BY_ID);
+
+ // keep 0-255 free for all Vanilla biomes
+ if (BiomesMixinPlugin.BIOME_IDS_BEYOND_255_SUPPORTED && id <= VanillaBiomes.MAX_ID) {
+ id = VanillaBiomes.MAX_ID + 1;
+ }
+ }
+
+ if (!BiomesMixinPlugin.BIOME_IDS_BEYOND_255_SUPPORTED && id > VanillaBiomes.MAX_ID) {
+ throw new IllegalStateException("Biome IDs above 255 are not supported at this time!"
+ + " Biome IDs should be limited to the range 0-255"
+ + " unless the save format has been modified to support IDs beyond 255.");
+ }
+
+ return id;
+ }
+
+ @Inject(
+ method = "",
+ at = @At(
+ value = "FIELD",
+ target = "Lnet/minecraft/world/biome/Biome;BY_ID:[Lnet/minecraft/world/biome/Biome;",
+ opcode = Opcodes.GETSTATIC,
+ args = "array=set"
+ )
+ )
+ private void osl$biomes$growArrays(int id, CallbackInfo ci) {
+ int capacity = id + 1;
+
+ BY_ID = DynamicArray.grow(BY_ID, capacity);
+ }
+}
diff --git a/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/resources/fabric.mod.json b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/resources/fabric.mod.json
new file mode 100644
index 00000000..e53ab100
--- /dev/null
+++ b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/resources/fabric.mod.json
@@ -0,0 +1,38 @@
+{
+ "schemaVersion": 1,
+ "id": "osl-biomes",
+ "version": "0.1.0+mcb1.8-pre1-mc1.6.4",
+ "environment": "*",
+ "entrypoints": {
+ "init": [
+ "net.ornithemc.osl.biomes.impl.BiomeRegistryImpl::init"
+ ]
+ },
+ "mixins": [
+ "osl.biomes.mixins.json"
+ ],
+ "accessWidener": "osl.biomes.classtweaker",
+ "depends": {
+ "fabricloader": "\u003e\u003d0.18.0",
+ "minecraft": "\u003e\u003d1.0.0-beta.8.0.1 \u003c\u003d1.6.4",
+ "osl-core": "\u003e\u003d0.9.0",
+ "osl-entrypoints": "\u003e\u003d0.5.0",
+ "osl-lifecycle-events": "\u003e\u003d0.6.0",
+ "osl-executors": "\u003e\u003d0.1.0",
+ "osl-text-components": "\u003e\u003d0.1.0-",
+ "osl-networking": "\u003e\u003d0.10.0",
+ "osl-networking-impl": "\u003e\u003d0.2.0",
+ "osl-registries": "\u003e\u003d0.1.0"
+ },
+ "name": "OSL Biomes",
+ "description": "Biomes API and events.",
+ "authors": [
+ "OrnitheMC"
+ ],
+ "contact": {
+ "homepage": "https://ornithemc.net/",
+ "issues": "https://github.com/OrnitheMC/ornithe-standard-libraries/issues",
+ "sources": "https://github.com/OrnitheMC/ornithe-standard-libraries"
+ },
+ "license": "Apache-2.0"
+}
\ No newline at end of file
diff --git a/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/resources/osl.biomes.classtweaker b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/resources/osl.biomes.classtweaker
new file mode 100644
index 00000000..03b8bf50
--- /dev/null
+++ b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/resources/osl.biomes.classtweaker
@@ -0,0 +1,14 @@
+classTweaker v1 named
+
+transitive-accessible method net/minecraft/world/biome/Biome (I)V
+transitive-accessible method net/minecraft/world/biome/Biome setTemperatureAndDownfall (FF)Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setHeight (FF)Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome disableRain ()Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setSnowy ()Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setName (Ljava/lang/String;)Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setMutatedColor (I)Lnet/minecraft/world/biome/Biome;
+transitive-accessible method net/minecraft/world/biome/Biome setBaseColor (I)Lnet/minecraft/world/biome/Biome;
+
+transitive-inject-interface net/minecraft/world/biome/Biome net/ornithemc/osl/biomes/impl/biome/BiomeExtensionImpl
+
+mutable field net/minecraft/world/biome/Biome id I
diff --git a/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/resources/osl.biomes.mixins.json b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/resources/osl.biomes.mixins.json
new file mode 100644
index 00000000..a674432b
--- /dev/null
+++ b/libraries/biomes/biomes-mcb1.8-pre1-mc1.6.4/src/main/resources/osl.biomes.mixins.json
@@ -0,0 +1,17 @@
+{
+ "required": true,
+ "minVersion": "0.8",
+ "package": "net.ornithemc.osl.biomes.impl.mixin",
+ "compatibilityLevel": "JAVA_8",
+ "plugin": "net.ornithemc.osl.biomes.impl.BiomesMixinPlugin",
+ "mixins": [
+ "common.BiomeMixin"
+ ],
+ "client": [
+ ],
+ "server": [
+ ],
+ "injectors": {
+ "defaultRequire": 1
+ }
+}
diff --git a/libraries/biomes/build.gradle b/libraries/biomes/build.gradle
new file mode 100644
index 00000000..e98ba2c6
--- /dev/null
+++ b/libraries/biomes/build.gradle
@@ -0,0 +1 @@
+setUpLibrary(project)
diff --git a/libraries/biomes/gradle.properties b/libraries/biomes/gradle.properties
new file mode 100644
index 00000000..8829b6f2
--- /dev/null
+++ b/libraries/biomes/gradle.properties
@@ -0,0 +1,7 @@
+library_id = biomes
+library_name = Biomes
+library_description = Biomes API and events.
+library_version = 0.1.0
+
+entrypoint_init = net.ornithemc.osl.biomes.impl.BiomeRegistryImpl::init
+osl_dependencies = core:0.9.0,entrypoints:0.5.0,registries:0.1.0
diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
index 87d5b78a..d99f797f 100644
--- a/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
+++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
@@ -2,6 +2,7 @@
import net.minecraft.block.Block;
import net.minecraft.item.Item;
+import net.minecraft.world.biome.Biome;
import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
@@ -15,6 +16,7 @@ public final class RegistryKeys {
public static final ResourceKey> BLOCK = from("block");
public static final ResourceKey> ITEM = from("item");
+ public static final ResourceKey> BIOME = from("biome");
/**
* Constructs a registry key with the default namespace and the given identifier.
diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
index 87d5b78a..d99f797f 100644
--- a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
+++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
@@ -2,6 +2,7 @@
import net.minecraft.block.Block;
import net.minecraft.item.Item;
+import net.minecraft.world.biome.Biome;
import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
@@ -15,6 +16,7 @@ public final class RegistryKeys {
public static final ResourceKey> BLOCK = from("block");
public static final ResourceKey> ITEM = from("item");
+ public static final ResourceKey> BIOME = from("biome");
/**
* Constructs a registry key with the default namespace and the given identifier.
diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
index 87d5b78a..d99f797f 100644
--- a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
+++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
@@ -2,6 +2,7 @@
import net.minecraft.block.Block;
import net.minecraft.item.Item;
+import net.minecraft.world.biome.Biome;
import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
@@ -15,6 +16,7 @@ public final class RegistryKeys {
public static final ResourceKey> BLOCK = from("block");
public static final ResourceKey> ITEM = from("item");
+ public static final ResourceKey> BIOME = from("biome");
/**
* Constructs a registry key with the default namespace and the given identifier.
diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
index 87d5b78a..d99f797f 100644
--- a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
+++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
@@ -2,6 +2,7 @@
import net.minecraft.block.Block;
import net.minecraft.item.Item;
+import net.minecraft.world.biome.Biome;
import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
@@ -15,6 +16,7 @@ public final class RegistryKeys {
public static final ResourceKey> BLOCK = from("block");
public static final ResourceKey> ITEM = from("item");
+ public static final ResourceKey> BIOME = from("biome");
/**
* Constructs a registry key with the default namespace and the given identifier.
diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
index 87d5b78a..d99f797f 100644
--- a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
+++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
@@ -2,6 +2,7 @@
import net.minecraft.block.Block;
import net.minecraft.item.Item;
+import net.minecraft.world.biome.Biome;
import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
@@ -15,6 +16,7 @@ public final class RegistryKeys {
public static final ResourceKey> BLOCK = from("block");
public static final ResourceKey> ITEM = from("item");
+ public static final ResourceKey> BIOME = from("biome");
/**
* Constructs a registry key with the default namespace and the given identifier.
diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
index 87d5b78a..d99f797f 100644
--- a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
+++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
@@ -2,6 +2,7 @@
import net.minecraft.block.Block;
import net.minecraft.item.Item;
+import net.minecraft.world.biome.Biome;
import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
@@ -15,6 +16,7 @@ public final class RegistryKeys {
public static final ResourceKey> BLOCK = from("block");
public static final ResourceKey> ITEM = from("item");
+ public static final ResourceKey> BIOME = from("biome");
/**
* Constructs a registry key with the default namespace and the given identifier.
diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
index 87d5b78a..d99f797f 100644
--- a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
+++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
@@ -2,6 +2,7 @@
import net.minecraft.block.Block;
import net.minecraft.item.Item;
+import net.minecraft.world.biome.Biome;
import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
@@ -15,6 +16,7 @@ public final class RegistryKeys {
public static final ResourceKey> BLOCK = from("block");
public static final ResourceKey> ITEM = from("item");
+ public static final ResourceKey> BIOME = from("biome");
/**
* Constructs a registry key with the default namespace and the given identifier.
diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
index 87d5b78a..d99f797f 100644
--- a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
+++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java
@@ -2,6 +2,7 @@
import net.minecraft.block.Block;
import net.minecraft.item.Item;
+import net.minecraft.world.biome.Biome;
import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
import net.ornithemc.osl.core.api.util.NamespacedIdentifiers;
@@ -15,6 +16,7 @@ public final class RegistryKeys {
public static final ResourceKey> BLOCK = from("block");
public static final ResourceKey> ITEM = from("item");
+ public static final ResourceKey> BIOME = from("biome");
/**
* Constructs a registry key with the default namespace and the given identifier.
diff --git a/settings.gradle b/settings.gradle
index e53df069..2c30edb0 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -22,6 +22,15 @@ include ':libraries:core'
include ':libraries:core:core-mca1.0.1_01-mc14w26c'
include ':libraries:core:core-mc14w27a-mc1.14.4'
+include ':libraries:biomes'
+include ':libraries:biomes:biomes-mcb1.8-pre1-mc1.6.4'
+include ':libraries:biomes:biomes-mc13w36a-mc1.8.2-pre4'
+include ':libraries:biomes:biomes-mc1.8.2-pre5-mc15w51b'
+include ':libraries:biomes:biomes-mc16w02a-mc18w05a'
+include ':libraries:biomes:biomes-mc18w06a-mc18w31a'
+include ':libraries:biomes:biomes-mc18w32a-mc1.13.2'
+include ':libraries:biomes:biomes-mc18w43a-mc1.14.4'
+
include ':libraries:blocks'
include ':libraries:blocks:blocks-mca1.0.1_01-mc1.6.4'
include ':libraries:blocks:blocks-mc13w36a-mc14w26c'