diff --git a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/api/BlockEvents.java b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/api/BlockEvents.java index c2d7af638..9a76f18be 100644 --- a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/api/BlockEvents.java +++ b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/api/BlockEvents.java @@ -22,7 +22,7 @@ public final class BlockEvents { *
 	 * {@code
 	 * BlockEvents.REGISTER_BLOCKS.register(() -> {
-	 * 	BlockRegistry.register(99, NamespacedIdentifiers.from("example", "cookie"), new CookieBlock());
+	 * 	BlockRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new CookieBlock());
 	 * });
 	 * }
 	 * 
diff --git a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java index 003e6ec54..ae6522ef9 100644 --- a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java +++ b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java @@ -6,12 +6,16 @@ import net.ornithemc.osl.blocks.impl.BlockRegistryImpl; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; /** * Public access to the Blocks registry. */ public final class BlockRegistry { + public static final DefaultedRegistry REGISTRY = BlockRegistryImpl.REGISTRY; + /** * @return the numerical ID assigned to the given block. */ @@ -22,7 +26,14 @@ public static int getId(Block block) { /** * @return the namespaced ID assigned to the given block. */ - public static NamespacedIdentifier getKey(Block block) { + public static NamespacedIdentifier getIdentifier(Block block) { + return BlockRegistryImpl.getIdentifier(block); + } + + /** + * @return the resource key assigned to the given block. + */ + public static ResourceKey getKey(Block block) { return BlockRegistryImpl.getKey(block); } @@ -36,24 +47,62 @@ public static Block getBlock(int id) { /** * @return the block mapped to the given namespaced ID. */ - public static Block getBlock(NamespacedIdentifier key) { + public static Block getBlock(NamespacedIdentifier identifier) { + return BlockRegistryImpl.getBlock(identifier); + } + + /** + * @return the block mapped to the given resource key. + */ + public static Block getBlock(ResourceKey key) { return BlockRegistryImpl.getBlock(key); } /** * @return a set containing all namespaced IDs in the registry. */ - public static Set keySet() { + public static Set identifierSet() { + return BlockRegistryImpl.identifierSet(); + } + + /** + * @return a set containing all resource keys in the registry. + */ + public static Set> keySet() { return BlockRegistryImpl.keySet(); } + /** + * @param the block type. + * @param identifier the namespaced ID of the block. + * @param block the block to register. + * @return the registered block. + */ + public static T register(NamespacedIdentifier identifier, T block) { + return BlockRegistryImpl.register(identifier, block); + } + + /** + * @param the block type. + * @param key the resource key of the block. + * @param block the block to register. + * @return the registered block. + */ + public static T register(ResourceKey key, T block) { + return BlockRegistryImpl.register(key, block); + } + /** * @param the block type. * @param id the numerical ID of the block. * @param key the namespaced ID of the block. * @param block the block to register. * @return the registered block. + * + * @deprecated use {@linkplain #register(NamespacedIdentifier, Block)} + * or {@linkplain #register(ResourceKey, Block)} instead. */ + @Deprecated public static T register(int id, NamespacedIdentifier key, T block) { return BlockRegistryImpl.register(id, key, block); } diff --git a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java index d8244fc98..51569a41a 100644 --- a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java +++ b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java @@ -1,72 +1,90 @@ package net.ornithemc.osl.blocks.impl; import java.util.Set; -import java.util.stream.Collectors; import net.minecraft.block.Block; import net.ornithemc.osl.blocks.api.BlockEvents; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; -import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +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 BlockRegistryImpl { + public static final DefaultedRegistry REGISTRY = VanillaRegistries.registerDefaulted(RegistryKeys.BLOCK, Block.REGISTRY); + private static boolean locked = true; - private static boolean initialized = false; public static int getId(Block block) { - return Block.REGISTRY.getId(block); + return REGISTRY.getId(block); + } + + public static NamespacedIdentifier getIdentifier(Block block) { + return REGISTRY.getIdentifier(block); } - public static NamespacedIdentifier getKey(Block block) { - String key = Block.REGISTRY.getKey(block); - return key == null ? null : NamespacedIdentifiers.parse(key); + public static ResourceKey getKey(Block block) { + return REGISTRY.getKey(block); } public static Block getBlock(int id) { - return Block.REGISTRY.get(id); + return REGISTRY.get(id); } - public static Block getBlock(NamespacedIdentifier key) { - return Block.REGISTRY.get(key.toString()); + public static Block getBlock(NamespacedIdentifier identifier) { + return REGISTRY.get(identifier); } - public static Set keySet() { - return Block.REGISTRY.keySet().stream().map(NamespacedIdentifiers::parse).collect(Collectors.toSet()); + public static Block getBlock(ResourceKey key) { + return REGISTRY.get(key); } - public static T register(int id, NamespacedIdentifier key, T block) { + public static Set identifierSet() { + return REGISTRY.identifierSet(); + } + + public static Set> keySet() { + return REGISTRY.keySet(); + } + + public static T register(NamespacedIdentifier identifier, T block) { if (locked) { - throw new IllegalStateException("register called too " + (initialized ? "late" : "early") + ": registry locked!"); + throw new IllegalStateException("register called too early: registry locked!"); } else { - Block.REGISTRY.register(id, key.toString(), block); + return Registry.register(REGISTRY, identifier, block); } + } - return block; + public static T register(ResourceKey key, T block) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, key, block); + } } - public static void lock() { - if (!initialized) { - throw new IllegalStateException("cannot lock block registry unless it's been initialized!"); + @Deprecated + public static T register(int id, NamespacedIdentifier key, T block) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, id, key, block); } + } - locked = true; + public static void init() { + SyncedRegistries.register(RegistryKeys.BLOCK); } public static void unlock() { - if (initialized) { - throw new IllegalStateException("cannot unlock block registry once it's been initialized!"); - } - locked = false; } - public static void init() { - if (locked) { - throw new IllegalStateException("cannot initialize block registry when it's locked!"); - } - + public static void registerBlocks() { BlockEvents.REGISTER_BLOCKS.invoker().run(); - initialized = true; } } diff --git a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/block/AirBlock.java b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/block/AirBlock.java index 183b3ac0d..d597e30c5 100644 --- a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/block/AirBlock.java +++ b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/block/AirBlock.java @@ -11,6 +11,11 @@ public AirBlock() { super(Material.AIR); } + @Override + public boolean isAir() { + return true; + } + @Override public int getRenderType() { return -1; diff --git a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockPostInit.java b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockPostInit.java new file mode 100644 index 000000000..1c4cdcef4 --- /dev/null +++ b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockPostInit.java @@ -0,0 +1,7 @@ +package net.ornithemc.osl.blocks.impl.block; + +public interface BlockPostInit { + + void osl$blocks$postInit(); + +} diff --git a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java index 407274083..83f2b2e54 100644 --- a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java +++ b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java @@ -1,20 +1,34 @@ package net.ornithemc.osl.blocks.impl.mixin.common; 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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import net.minecraft.block.Block; +import net.minecraft.entity.living.mob.monster.EndermanEntity; +import net.ornithemc.osl.blocks.api.BlockRegistry; import net.ornithemc.osl.blocks.api.block.BlockExtension; import net.ornithemc.osl.blocks.impl.BlockRegistryImpl; import net.ornithemc.osl.blocks.impl.BlocksMixinPlugin; import net.ornithemc.osl.blocks.impl.block.AirBlock; +import net.ornithemc.osl.blocks.impl.block.BlockPostInit; +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.core.impl.util.Util; +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.api.registry.SyncedRegistries; +import net.ornithemc.osl.registries.api.registry.sync.BooleanArrayMapper; @Mixin(Block.class) public class BlockMixin implements BlockExtension { + @Shadow + private String key; + @Inject( method = "init", at = @At( @@ -36,14 +50,47 @@ public class BlockMixin implements BlockExtension { target = "Lnet/minecraft/util/registry/IdRegistry;iterator()Ljava/util/Iterator;" ) ) - private static void osl$blocks$initAndLockBlockRegistry(CallbackInfo ci) { - BlockRegistryImpl.init(); - BlockRegistryImpl.lock(); + private static void osl$blocks$registerBlocks(CallbackInfo ci) { + BlockRegistryImpl.registerBlocks(); + + for (Block block : Block.REGISTRY) { + if (block instanceof BlockPostInit) { + ((BlockPostInit) block).osl$blocks$postInit(); + } + } + } + + @Inject( + method = "init", + at = @At( + value = "TAIL" + ) + ) + private static void osl$blocks$registerArrayMappers(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block/enderman_holdable"), BooleanArrayMapper.of(EndermanEntity.HOLDABLE_BLOCKS)); + } + + @Inject( + method = "getTranslationKey", + at = @At( + value = "HEAD" + ) + ) + private void osl$blocks$autoAssignTranslationKey(CallbackInfoReturnable cir) { + if (this.key == null) { + NamespacedIdentifier identifier = BlockRegistry.getIdentifier((Block) (Object) this); + + if (identifier == null) { + this.key = "unknown"; + } else { + this.key = Util.makeTranslationKey(identifier); + } + } } @Override public String toString() { - return "Block{" + BlockRegistryImpl.getKey((Block) (Object) this) + "}"; + return "Block{" + BlockRegistryImpl.getIdentifier((Block) (Object) this) + "}"; } @Override diff --git a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/EndermanEntityMixin.java b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/EndermanEntityMixin.java new file mode 100644 index 000000000..7547898bf --- /dev/null +++ b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/EndermanEntityMixin.java @@ -0,0 +1,48 @@ +package net.ornithemc.osl.blocks.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.Inject; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.block.Block; +import net.minecraft.entity.living.mob.monster.EndermanEntity; + +import net.ornithemc.osl.registries.api.registry.sync.DynamicArrays; + +@Mixin(EndermanEntity.class) +public class EndermanEntityMixin { + + // what the fuck, mojang? + @Shadow @Final @Mutable + private static boolean[] HOLDABLE_BLOCKS; + + @Inject( + method = "", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/entity/living/mob/monster/EndermanEntity;HOLDABLE_BLOCKS:[Z", + opcode = Opcodes.PUTSTATIC, + shift = Shift.AFTER + ) + ) + private static void osl$blocks$growArray(CallbackInfo ci) { + int capacity = HOLDABLE_BLOCKS.length; + + for (Block block : Block.REGISTRY) { + int required = Block.getId(block) + 1; + + if (required > capacity) { + capacity = required; + } + } + + HOLDABLE_BLOCKS = DynamicArrays.grow(HOLDABLE_BLOCKS, capacity); + } +} diff --git a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/FireBlockMixin.java b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/FireBlockMixin.java new file mode 100644 index 000000000..5db1b443b --- /dev/null +++ b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/FireBlockMixin.java @@ -0,0 +1,53 @@ +package net.ornithemc.osl.blocks.impl.mixin.common; + +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.block.FireBlock; + +import net.ornithemc.osl.blocks.api.BlockRegistry; +import net.ornithemc.osl.blocks.impl.block.BlockPostInit; +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.api.registry.SyncedRegistries; +import net.ornithemc.osl.registries.api.registry.sync.DynamicArrays; +import net.ornithemc.osl.registries.api.registry.sync.IntArrayMapper; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +@Mixin(FireBlock.class) +public class FireBlockMixin implements BlockPostInit { + + @Shadow + private int[] flammability; + @Shadow + private int[] burnChance; + + @Inject( + method = "setFlammable", + at = @At( + value = "HEAD" + ) + ) + private void osl$blocks$growArrays(int block, int flammability, int burnChance, CallbackInfo ci) { + int capacity = block + 1; + + this.flammability = DynamicArrays.grow(this.flammability, capacity); + this.burnChance = DynamicArrays.grow(this.burnChance, capacity); + } + + @Override + public void osl$blocks$postInit() { + FireBlock block = (FireBlock) (Object) this; + NamespacedIdentifier identifier = BlockRegistry.getIdentifier(block); + + if (identifier == null) { + RegistriesImpl.LOGGER.warn("Unable to register FireBlock array mappers for unregistered block {}", block); + } else { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, identifier.suffixed("/flammability"), IntArrayMapper.of(this.flammability)); + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, identifier.suffixed("/burn_chance"), IntArrayMapper.of(this.burnChance)); + } + } +} diff --git a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/StatsMixin.java b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/StatsMixin.java new file mode 100644 index 000000000..880fc854d --- /dev/null +++ b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/StatsMixin.java @@ -0,0 +1,44 @@ +package net.ornithemc.osl.blocks.impl.mixin.common; + +import java.util.Map; + +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.stat.Stat; +import net.minecraft.stat.Stats; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.core.impl.util.MinecraftVersion; +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.api.registry.SyncedRegistries; +import net.ornithemc.osl.registries.api.registry.sync.ObjectArrayMapper; +import net.ornithemc.osl.registries.impl.registry.sync.StatsMapper; + +@Mixin(Stats.class) +public class StatsMixin { + + @Shadow @Final + private static Map BY_KEY; + @Shadow @Final + private static Stat[] BLOCKS_MINED; + + @Inject( + // inject at init instead of in case the arrays are resized... + method = "init", + at = @At( + value = "TAIL" + ) + ) + private static void osl$items$registerStatsMapper(CallbackInfo ci) { + if (MinecraftVersion.resolve().compareTo("14w06a") < 0) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("stats/mined"), StatsMapper.of(BY_KEY, BLOCKS_MINED)); + } else { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("stats/mined"), ObjectArrayMapper.of(BLOCKS_MINED)); + } + } +} diff --git a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/resources/fabric.mod.json b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/resources/fabric.mod.json index 2730c538b..d63ce5ab3 100644 --- a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/resources/fabric.mod.json +++ b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/resources/fabric.mod.json @@ -3,6 +3,11 @@ "id": "osl-blocks", "version": "0.1.1+mc13w36a-mc14w26c", "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.blocks.impl.BlockRegistryImpl::init" + ] + }, "mixins": [ "osl.blocks.mixins.json" ], @@ -10,7 +15,14 @@ "depends": { "fabricloader": "\u003e\u003d0.18.0", "minecraft": "\u003e\u003d1.7-alpha.13.36.a \u003c\u003d1.8-alpha.14.26.c", - "osl-core": "\u003e\u003d0.9.0" + "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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0", + "osl-registries": "\u003e\u003d0.1.0-" }, "name": "OSL Blocks", "description": "Blocks API and events.", diff --git a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/resources/osl.blocks.classtweaker b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/resources/osl.blocks.classtweaker index e8fc2dcbf..7ea8571ed 100644 --- a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/resources/osl.blocks.classtweaker +++ b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/resources/osl.blocks.classtweaker @@ -12,4 +12,7 @@ transitive-accessible method net/minecraft/block/Block setCreativeModeTab (Lnet/ transitive-accessible method net/minecraft/block/Block setSpriteName (Ljava/lang/String;)Lnet/minecraft/block/Block; transitive-inject-interface net/minecraft/block/Block net/ornithemc/osl/blocks/impl/block/BlockExtensionImpl -transitive-inject-interface net/minecraft/block/Blocks net/ornithemc/osl/blocks/impl/block/BlocksExtensionImpl \ No newline at end of file +transitive-inject-interface net/minecraft/block/Blocks net/ornithemc/osl/blocks/impl/block/BlocksExtensionImpl + +accessible field net/minecraft/entity/living/mob/monster/EndermanEntity HOLDABLE_BLOCKS [Z + diff --git a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/resources/osl.blocks.mixins.json b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/resources/osl.blocks.mixins.json index be211c149..f6bd4d28c 100644 --- a/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/resources/osl.blocks.mixins.json +++ b/libraries/blocks/blocks-mc13w36a-mc14w26c/src/main/resources/osl.blocks.mixins.json @@ -7,7 +7,10 @@ "mixins": [ "common.AirBlockMixin", "common.BlockMixin", - "common.BlocksMixin" + "common.BlocksMixin", + "common.EndermanEntityMixin", + "common.FireBlockMixin", + "common.StatsMixin" ], "client": [ ], diff --git a/libraries/blocks/blocks-mc14w27a-mc17w46a/build.gradle b/libraries/blocks/blocks-mc14w27a-mc15w35a/build.gradle similarity index 100% rename from libraries/blocks/blocks-mc14w27a-mc17w46a/build.gradle rename to libraries/blocks/blocks-mc14w27a-mc15w35a/build.gradle diff --git a/libraries/blocks/blocks-mc14w27a-mc15w35a/gradle.properties b/libraries/blocks/blocks-mc14w27a-mc15w35a/gradle.properties new file mode 100644 index 000000000..7b3826dbc --- /dev/null +++ b/libraries/blocks/blocks-mc14w27a-mc15w35a/gradle.properties @@ -0,0 +1,5 @@ +min_mc_version = 14w27a +max_mc_version = 15w35a +minecraft_dependency = >=1.8-alpha.14.27.a <=1.9-alpha.15.35.a + +minecraft_version = 1.8.9 diff --git a/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/BlockEvents.java b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/api/BlockEvents.java similarity index 88% rename from libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/BlockEvents.java rename to libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/api/BlockEvents.java index c2d7af638..9a76f18be 100644 --- a/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/BlockEvents.java +++ b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/api/BlockEvents.java @@ -22,7 +22,7 @@ public final class BlockEvents { *
 	 * {@code
 	 * BlockEvents.REGISTER_BLOCKS.register(() -> {
-	 * 	BlockRegistry.register(99, NamespacedIdentifiers.from("example", "cookie"), new CookieBlock());
+	 * 	BlockRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new CookieBlock());
 	 * });
 	 * }
 	 * 
diff --git a/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java new file mode 100644 index 000000000..ae6522ef9 --- /dev/null +++ b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java @@ -0,0 +1,109 @@ +package net.ornithemc.osl.blocks.api; + +import java.util.Set; + +import net.minecraft.block.Block; + +import net.ornithemc.osl.blocks.impl.BlockRegistryImpl; +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +/** + * Public access to the Blocks registry. + */ +public final class BlockRegistry { + + public static final DefaultedRegistry REGISTRY = BlockRegistryImpl.REGISTRY; + + /** + * @return the numerical ID assigned to the given block. + */ + public static int getId(Block block) { + return BlockRegistryImpl.getId(block); + } + + /** + * @return the namespaced ID assigned to the given block. + */ + public static NamespacedIdentifier getIdentifier(Block block) { + return BlockRegistryImpl.getIdentifier(block); + } + + /** + * @return the resource key assigned to the given block. + */ + public static ResourceKey getKey(Block block) { + return BlockRegistryImpl.getKey(block); + } + + /** + * @return the block mapped to the given numerical ID. + */ + public static Block getBlock(int id) { + return BlockRegistryImpl.getBlock(id); + } + + /** + * @return the block mapped to the given namespaced ID. + */ + public static Block getBlock(NamespacedIdentifier identifier) { + return BlockRegistryImpl.getBlock(identifier); + } + + /** + * @return the block mapped to the given resource key. + */ + public static Block getBlock(ResourceKey key) { + return BlockRegistryImpl.getBlock(key); + } + + /** + * @return a set containing all namespaced IDs in the registry. + */ + public static Set identifierSet() { + return BlockRegistryImpl.identifierSet(); + } + + /** + * @return a set containing all resource keys in the registry. + */ + public static Set> keySet() { + return BlockRegistryImpl.keySet(); + } + + /** + * @param the block type. + * @param identifier the namespaced ID of the block. + * @param block the block to register. + * @return the registered block. + */ + public static T register(NamespacedIdentifier identifier, T block) { + return BlockRegistryImpl.register(identifier, block); + } + + /** + * @param the block type. + * @param key the resource key of the block. + * @param block the block to register. + * @return the registered block. + */ + public static T register(ResourceKey key, T block) { + return BlockRegistryImpl.register(key, block); + } + + /** + * @param the block type. + * @param id the numerical ID of the block. + * @param key the namespaced ID of the block. + * @param block the block to register. + * @return the registered block. + * + * @deprecated use {@linkplain #register(NamespacedIdentifier, Block)} + * or {@linkplain #register(ResourceKey, Block)} instead. + */ + @Deprecated + public static T register(int id, NamespacedIdentifier key, T block) { + return BlockRegistryImpl.register(id, key, block); + } +} diff --git a/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/block/BlockExtension.java b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/api/block/BlockExtension.java similarity index 100% rename from libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/block/BlockExtension.java rename to libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/api/block/BlockExtension.java diff --git a/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java new file mode 100644 index 000000000..3707a727b --- /dev/null +++ b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java @@ -0,0 +1,93 @@ +package net.ornithemc.osl.blocks.impl; + +import java.util.Set; + +import net.minecraft.block.Block; + +import net.ornithemc.osl.blocks.api.BlockEvents; +import net.ornithemc.osl.blocks.impl.block.BlockStateRegistryFixer; +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +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 BlockRegistryImpl { + + public static final DefaultedRegistry REGISTRY = VanillaRegistries.registerDefaulted(RegistryKeys.BLOCK, Block.REGISTRY); + + private static boolean locked = true; + + public static int getId(Block block) { + return REGISTRY.getId(block); + } + + public static NamespacedIdentifier getIdentifier(Block block) { + return REGISTRY.getIdentifier(block); + } + + public static ResourceKey getKey(Block block) { + return REGISTRY.getKey(block); + } + + public static Block getBlock(int id) { + return REGISTRY.get(id); + } + + public static Block getBlock(NamespacedIdentifier identifier) { + return REGISTRY.get(identifier); + } + + public static Block getBlock(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 block) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, identifier, block); + } + } + + public static T register(ResourceKey key, T block) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, key, block); + } + } + + @Deprecated + public static T register(int id, NamespacedIdentifier key, T block) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, id, key, block); + } + } + + public static void init() { + SyncedRegistries.register(RegistryKeys.BLOCK); + SyncedRegistries.registerFixer(RegistryKeys.BLOCK, NamespacedIdentifiers.from("blockstate"), new BlockStateRegistryFixer()); + } + + public static void unlock() { + locked = false; + } + + public static void registerBlocks() { + BlockEvents.REGISTER_BLOCKS.invoker().run(); + } +} diff --git a/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockExtensionImpl.java b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockExtensionImpl.java similarity index 100% rename from libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockExtensionImpl.java rename to libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockExtensionImpl.java diff --git a/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockStateRegistryFixer.java b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockStateRegistryFixer.java new file mode 100644 index 000000000..9f42817d0 --- /dev/null +++ b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockStateRegistryFixer.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.blocks.impl.block; + +import net.minecraft.block.Block; +import net.minecraft.block.state.BlockState; +import net.ornithemc.osl.blocks.api.BlockRegistry; +import net.ornithemc.osl.registries.api.registry.sync.IdFixer; +import net.ornithemc.osl.registries.impl.access.Clearable; + +public class BlockStateRegistryFixer implements IdFixer { + + @Override + public void apply() { + Clearable.clear(Block.STATE_REGISTRY); + + for (Block block : BlockRegistry.REGISTRY) { + int blockId = BlockRegistry.getId(block); + + for (BlockState state : block.stateDefinition().all()) { + int metadata = block.getMetadataFromState(state); + int stateId = blockId << 4 | metadata; + + Block.STATE_REGISTRY.put(state, stateId); + } + } + } +} diff --git a/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/AirBlockMixin.java b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/AirBlockMixin.java similarity index 100% rename from libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/AirBlockMixin.java rename to libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/AirBlockMixin.java diff --git a/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java similarity index 51% rename from libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java rename to libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java index 6b4e6bf51..95961cce2 100644 --- a/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java +++ b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java @@ -1,18 +1,26 @@ package net.ornithemc.osl.blocks.impl.mixin.common; 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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import net.minecraft.block.Block; +import net.ornithemc.osl.blocks.api.BlockRegistry; import net.ornithemc.osl.blocks.api.block.BlockExtension; import net.ornithemc.osl.blocks.impl.BlockRegistryImpl; +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.impl.util.Util; @Mixin(Block.class) public class BlockMixin implements BlockExtension { + @Shadow + private String key; + @Inject( method = "init", at = @At( @@ -30,9 +38,26 @@ public class BlockMixin implements BlockExtension { target = "Lnet/minecraft/util/registry/DefaultedIdRegistry;validate()V" ) ) - private static void osl$blocks$initAndLockBlockRegistry(CallbackInfo ci) { - BlockRegistryImpl.init(); - BlockRegistryImpl.lock(); + private static void osl$blocks$registerBlocks(CallbackInfo ci) { + BlockRegistryImpl.registerBlocks(); + } + + @Inject( + method = "getTranslationKey", + at = @At( + value = "HEAD" + ) + ) + private void osl$blocks$autoAssignTranslationKey(CallbackInfoReturnable cir) { + if (this.key == null) { + NamespacedIdentifier identifier = BlockRegistry.getIdentifier((Block) (Object) this); + + if (identifier == null) { + this.key = "unknown"; + } else { + this.key = Util.makeTranslationKey(identifier); + } + } } @Override diff --git a/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/StatsMixin.java b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/StatsMixin.java new file mode 100644 index 000000000..019e93566 --- /dev/null +++ b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/StatsMixin.java @@ -0,0 +1,34 @@ +package net.ornithemc.osl.blocks.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.stat.Stat; +import net.minecraft.stat.Stats; + +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.ObjectArrayMapper; + +@Mixin(Stats.class) +public class StatsMixin { + + @Shadow @Final + private static Stat[] BLOCKS_MINED; + + @Inject( + // inject at init instead of in case the arrays are resized... + method = "init", + at = @At( + value = "TAIL" + ) + ) + private static void osl$items$registerStatsMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("stats/mined"), ObjectArrayMapper.of(BLOCKS_MINED)); + } +} diff --git a/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/resources/fabric.mod.json b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..bbd4042bc --- /dev/null +++ b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/resources/fabric.mod.json @@ -0,0 +1,38 @@ +{ + "schemaVersion": 1, + "id": "osl-blocks", + "version": "0.1.1+mc14w27a-mc15w35a", + "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.blocks.impl.BlockRegistryImpl::init" + ] + }, + "mixins": [ + "osl.blocks.mixins.json" + ], + "accessWidener": "osl.blocks.classtweaker", + "depends": { + "fabricloader": "\u003e\u003d0.18.0", + "minecraft": "\u003e\u003d1.8-alpha.14.27.a \u003c\u003d1.9-alpha.15.35.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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0", + "osl-registries": "\u003e\u003d0.1.0-" + }, + "name": "OSL Blocks", + "description": "Blocks 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/blocks/blocks-mc14w27a-mc15w35a/src/main/resources/osl.blocks.classtweaker b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/resources/osl.blocks.classtweaker new file mode 100644 index 000000000..73c405d73 --- /dev/null +++ b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/resources/osl.blocks.classtweaker @@ -0,0 +1,14 @@ +classTweaker v1 named + +transitive-accessible method net/minecraft/block/Block setSounds (Lnet/minecraft/block/Block$Sounds;)Lnet/minecraft/block/Block; +transitive-accessible method net/minecraft/block/Block setOpacity (I)Lnet/minecraft/block/Block; +transitive-accessible method net/minecraft/block/Block setLight (F)Lnet/minecraft/block/Block; +transitive-accessible method net/minecraft/block/Block setBlastResistance (F)Lnet/minecraft/block/Block; +transitive-accessible method net/minecraft/block/Block setStrength (F)Lnet/minecraft/block/Block; +transitive-accessible method net/minecraft/block/Block setUnbreakable ()Lnet/minecraft/block/Block; +transitive-accessible method net/minecraft/block/Block setTicksRandomly (Z)Lnet/minecraft/block/Block; +transitive-accessible method net/minecraft/block/Block setKey (Ljava/lang/String;)Lnet/minecraft/block/Block; +transitive-accessible method net/minecraft/block/Block disableStats ()Lnet/minecraft/block/Block; +transitive-accessible method net/minecraft/block/Block setCreativeModeTab (Lnet/minecraft/item/CreativeModeTab;)Lnet/minecraft/block/Block; + +transitive-inject-interface net/minecraft/block/Block net/ornithemc/osl/blocks/impl/block/BlockExtensionImpl \ No newline at end of file diff --git a/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/resources/osl.blocks.mixins.json b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/resources/osl.blocks.mixins.json similarity index 84% rename from libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/resources/osl.blocks.mixins.json rename to libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/resources/osl.blocks.mixins.json index 7f2c19c8f..0b4c0fa73 100644 --- a/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/resources/osl.blocks.mixins.json +++ b/libraries/blocks/blocks-mc14w27a-mc15w35a/src/main/resources/osl.blocks.mixins.json @@ -5,7 +5,8 @@ "compatibilityLevel": "JAVA_8", "mixins": [ "common.AirBlockMixin", - "common.BlockMixin" + "common.BlockMixin", + "common.StatsMixin" ], "client": [ ], diff --git a/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java b/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java deleted file mode 100644 index 003e6ec54..000000000 --- a/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java +++ /dev/null @@ -1,60 +0,0 @@ -package net.ornithemc.osl.blocks.api; - -import java.util.Set; - -import net.minecraft.block.Block; - -import net.ornithemc.osl.blocks.impl.BlockRegistryImpl; -import net.ornithemc.osl.core.api.util.NamespacedIdentifier; - -/** - * Public access to the Blocks registry. - */ -public final class BlockRegistry { - - /** - * @return the numerical ID assigned to the given block. - */ - public static int getId(Block block) { - return BlockRegistryImpl.getId(block); - } - - /** - * @return the namespaced ID assigned to the given block. - */ - public static NamespacedIdentifier getKey(Block block) { - return BlockRegistryImpl.getKey(block); - } - - /** - * @return the block mapped to the given numerical ID. - */ - public static Block getBlock(int id) { - return BlockRegistryImpl.getBlock(id); - } - - /** - * @return the block mapped to the given namespaced ID. - */ - public static Block getBlock(NamespacedIdentifier key) { - return BlockRegistryImpl.getBlock(key); - } - - /** - * @return a set containing all namespaced IDs in the registry. - */ - public static Set keySet() { - return BlockRegistryImpl.keySet(); - } - - /** - * @param the block type. - * @param id the numerical ID of the block. - * @param key the namespaced ID of the block. - * @param block the block to register. - * @return the registered block. - */ - public static T register(int id, NamespacedIdentifier key, T block) { - return BlockRegistryImpl.register(id, key, block); - } -} diff --git a/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java b/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java deleted file mode 100644 index 287364453..000000000 --- a/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java +++ /dev/null @@ -1,75 +0,0 @@ -package net.ornithemc.osl.blocks.impl; - -import java.util.Collections; -import java.util.Set; - -import net.minecraft.block.Block; -import net.minecraft.resource.Identifier; - -import net.ornithemc.osl.blocks.api.BlockEvents; -import net.ornithemc.osl.core.api.util.NamespacedIdentifier; - -public final class BlockRegistryImpl { - - private static boolean locked = true; - private static boolean initialized = false; - - public static int getId(Block block) { - return Block.REGISTRY.getId(block); - } - - public static NamespacedIdentifier getKey(Block block) { - return Block.REGISTRY.getKey(block); - } - - public static Block getBlock(int id) { - return Block.REGISTRY.get(id); - } - - public static Block getBlock(NamespacedIdentifier key) { - return Block.REGISTRY.get(identifier(key)); - } - - public static Set keySet() { - return Collections.unmodifiableSet(Block.REGISTRY.keySet()); - } - - public static T register(int id, NamespacedIdentifier key, T block) { - if (locked) { - throw new IllegalStateException("register called too " + (initialized ? "late" : "early") + ": registry locked!"); - } else { - Block.REGISTRY.register(id, identifier(key), block); - } - - return block; - } - - private static Identifier identifier(NamespacedIdentifier id) { - return id instanceof Identifier ? (Identifier) id : new Identifier(id.namespace(), id.identifier()); - } - - public static void lock() { - if (!initialized) { - throw new IllegalStateException("cannot lock block registry unless it's been initialized!"); - } - - locked = true; - } - - public static void unlock() { - if (initialized) { - throw new IllegalStateException("cannot unlock block registry once it's been initialized!"); - } - - locked = false; - } - - public static void init() { - if (locked) { - throw new IllegalStateException("cannot initialize block registry when it's locked!"); - } - - BlockEvents.REGISTER_BLOCKS.invoker().run(); - initialized = true; - } -} diff --git a/libraries/blocks/blocks-mc15w36a-mc17w46a/build.gradle b/libraries/blocks/blocks-mc15w36a-mc17w46a/build.gradle new file mode 100644 index 000000000..0a350fdb3 --- /dev/null +++ b/libraries/blocks/blocks-mc15w36a-mc17w46a/build.gradle @@ -0,0 +1 @@ +setUpModule(project) diff --git a/libraries/blocks/blocks-mc15w36a-mc17w46a/gradle.properties b/libraries/blocks/blocks-mc15w36a-mc17w46a/gradle.properties new file mode 100644 index 000000000..a313c7528 --- /dev/null +++ b/libraries/blocks/blocks-mc15w36a-mc17w46a/gradle.properties @@ -0,0 +1,7 @@ +min_mc_version = 15w36a +max_mc_version = 17w46a +minecraft_dependency = >=1.9-alpha.15.36.a <=1.13-alpha.17.46.a + +minecraft_version = 1.12.2 +raven_build = 1 +sparrow_build = 1 diff --git a/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/BlockEvents.java b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/BlockEvents.java new file mode 100644 index 000000000..9a76f18be --- /dev/null +++ b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/BlockEvents.java @@ -0,0 +1,34 @@ +package net.ornithemc.osl.blocks.api; + +import net.ornithemc.osl.core.api.events.Event; + +/** + * Events related to the blocks lifecycle. + */ +public final class BlockEvents { + + /** + * This event is invoked upon game start-up, after Vanilla block registration is finished. + * + *

+ * Custom block registration should be done in a listener of this event. + * Helper methods for registering blocks can be found in the {@linkplain + * BlockRegistry} class. + * + *

+ * Listeners to this event should be registered in your mod's entrypoint, + * and can be done as follows: + * + *

+	 * {@code
+	 * BlockEvents.REGISTER_BLOCKS.register(() -> {
+	 * 	BlockRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new CookieBlock());
+	 * });
+	 * }
+	 * 
+ * + * @see BlockRegistry + */ + public static final Event REGISTER_BLOCKS = Event.runnable(); + +} diff --git a/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java new file mode 100644 index 000000000..ae6522ef9 --- /dev/null +++ b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java @@ -0,0 +1,109 @@ +package net.ornithemc.osl.blocks.api; + +import java.util.Set; + +import net.minecraft.block.Block; + +import net.ornithemc.osl.blocks.impl.BlockRegistryImpl; +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +/** + * Public access to the Blocks registry. + */ +public final class BlockRegistry { + + public static final DefaultedRegistry REGISTRY = BlockRegistryImpl.REGISTRY; + + /** + * @return the numerical ID assigned to the given block. + */ + public static int getId(Block block) { + return BlockRegistryImpl.getId(block); + } + + /** + * @return the namespaced ID assigned to the given block. + */ + public static NamespacedIdentifier getIdentifier(Block block) { + return BlockRegistryImpl.getIdentifier(block); + } + + /** + * @return the resource key assigned to the given block. + */ + public static ResourceKey getKey(Block block) { + return BlockRegistryImpl.getKey(block); + } + + /** + * @return the block mapped to the given numerical ID. + */ + public static Block getBlock(int id) { + return BlockRegistryImpl.getBlock(id); + } + + /** + * @return the block mapped to the given namespaced ID. + */ + public static Block getBlock(NamespacedIdentifier identifier) { + return BlockRegistryImpl.getBlock(identifier); + } + + /** + * @return the block mapped to the given resource key. + */ + public static Block getBlock(ResourceKey key) { + return BlockRegistryImpl.getBlock(key); + } + + /** + * @return a set containing all namespaced IDs in the registry. + */ + public static Set identifierSet() { + return BlockRegistryImpl.identifierSet(); + } + + /** + * @return a set containing all resource keys in the registry. + */ + public static Set> keySet() { + return BlockRegistryImpl.keySet(); + } + + /** + * @param the block type. + * @param identifier the namespaced ID of the block. + * @param block the block to register. + * @return the registered block. + */ + public static T register(NamespacedIdentifier identifier, T block) { + return BlockRegistryImpl.register(identifier, block); + } + + /** + * @param the block type. + * @param key the resource key of the block. + * @param block the block to register. + * @return the registered block. + */ + public static T register(ResourceKey key, T block) { + return BlockRegistryImpl.register(key, block); + } + + /** + * @param the block type. + * @param id the numerical ID of the block. + * @param key the namespaced ID of the block. + * @param block the block to register. + * @return the registered block. + * + * @deprecated use {@linkplain #register(NamespacedIdentifier, Block)} + * or {@linkplain #register(ResourceKey, Block)} instead. + */ + @Deprecated + public static T register(int id, NamespacedIdentifier key, T block) { + return BlockRegistryImpl.register(id, key, block); + } +} diff --git a/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/block/BlockExtension.java b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/block/BlockExtension.java new file mode 100644 index 000000000..d3cc82edc --- /dev/null +++ b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/api/block/BlockExtension.java @@ -0,0 +1,10 @@ +package net.ornithemc.osl.blocks.api.block; + +public interface BlockExtension { + + /** + * @return whether this block is air. + */ + boolean isAir(); + +} diff --git a/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java new file mode 100644 index 000000000..3707a727b --- /dev/null +++ b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java @@ -0,0 +1,93 @@ +package net.ornithemc.osl.blocks.impl; + +import java.util.Set; + +import net.minecraft.block.Block; + +import net.ornithemc.osl.blocks.api.BlockEvents; +import net.ornithemc.osl.blocks.impl.block.BlockStateRegistryFixer; +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +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 BlockRegistryImpl { + + public static final DefaultedRegistry REGISTRY = VanillaRegistries.registerDefaulted(RegistryKeys.BLOCK, Block.REGISTRY); + + private static boolean locked = true; + + public static int getId(Block block) { + return REGISTRY.getId(block); + } + + public static NamespacedIdentifier getIdentifier(Block block) { + return REGISTRY.getIdentifier(block); + } + + public static ResourceKey getKey(Block block) { + return REGISTRY.getKey(block); + } + + public static Block getBlock(int id) { + return REGISTRY.get(id); + } + + public static Block getBlock(NamespacedIdentifier identifier) { + return REGISTRY.get(identifier); + } + + public static Block getBlock(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 block) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, identifier, block); + } + } + + public static T register(ResourceKey key, T block) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, key, block); + } + } + + @Deprecated + public static T register(int id, NamespacedIdentifier key, T block) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, id, key, block); + } + } + + public static void init() { + SyncedRegistries.register(RegistryKeys.BLOCK); + SyncedRegistries.registerFixer(RegistryKeys.BLOCK, NamespacedIdentifiers.from("blockstate"), new BlockStateRegistryFixer()); + } + + public static void unlock() { + locked = false; + } + + public static void registerBlocks() { + BlockEvents.REGISTER_BLOCKS.invoker().run(); + } +} diff --git a/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/BlocksMixinPlugin.java b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/BlocksMixinPlugin.java new file mode 100644 index 000000000..4a1d09228 --- /dev/null +++ b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/BlocksMixinPlugin.java @@ -0,0 +1,49 @@ +package net.ornithemc.osl.blocks.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 BlocksMixinPlugin implements IMixinConfigPlugin { + + @Override + public void onLoad(String mixinPackage) { + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if ("net.ornithemc.osl.blocks.impl.mixin.client.BlockColorsMixin".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("16w02a") >= 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/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockExtensionImpl.java b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockExtensionImpl.java new file mode 100644 index 000000000..5f35a77d9 --- /dev/null +++ b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockExtensionImpl.java @@ -0,0 +1,11 @@ +package net.ornithemc.osl.blocks.impl.block; + +import net.ornithemc.osl.blocks.api.block.BlockExtension; + +public interface BlockExtensionImpl extends BlockExtension { + + @Override + default boolean isAir() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockStateRegistryFixer.java b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockStateRegistryFixer.java new file mode 100644 index 000000000..9f42817d0 --- /dev/null +++ b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockStateRegistryFixer.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.blocks.impl.block; + +import net.minecraft.block.Block; +import net.minecraft.block.state.BlockState; +import net.ornithemc.osl.blocks.api.BlockRegistry; +import net.ornithemc.osl.registries.api.registry.sync.IdFixer; +import net.ornithemc.osl.registries.impl.access.Clearable; + +public class BlockStateRegistryFixer implements IdFixer { + + @Override + public void apply() { + Clearable.clear(Block.STATE_REGISTRY); + + for (Block block : BlockRegistry.REGISTRY) { + int blockId = BlockRegistry.getId(block); + + for (BlockState state : block.stateDefinition().all()) { + int metadata = block.getMetadataFromState(state); + int stateId = blockId << 4 | metadata; + + Block.STATE_REGISTRY.put(state, stateId); + } + } + } +} diff --git a/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/client/BlockColorsMixin.java b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/client/BlockColorsMixin.java new file mode 100644 index 000000000..4cb0a6c32 --- /dev/null +++ b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/client/BlockColorsMixin.java @@ -0,0 +1,34 @@ +package net.ornithemc.osl.blocks.impl.mixin.client; + +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.client.world.color.BlockColor; +import net.minecraft.client.world.color.BlockColors; +import net.minecraft.util.Id2ObjectBiMap; + +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(BlockColors.class) +public class BlockColorsMixin { + + @Shadow @Final + private Id2ObjectBiMap registry; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$registerModelRegistryMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block_color"), Id2ObjectBiMapMapper.of(this.registry)); + } +} diff --git a/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/AirBlockMixin.java b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/AirBlockMixin.java new file mode 100644 index 000000000..0fd9972c5 --- /dev/null +++ b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/AirBlockMixin.java @@ -0,0 +1,16 @@ +package net.ornithemc.osl.blocks.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; + +import net.minecraft.block.AirBlock; + +import net.ornithemc.osl.blocks.api.block.BlockExtension; + +@Mixin(AirBlock.class) +public class AirBlockMixin implements BlockExtension { + + @Override + public boolean isAir() { + return true; + } +} diff --git a/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java new file mode 100644 index 000000000..95961cce2 --- /dev/null +++ b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java @@ -0,0 +1,67 @@ +package net.ornithemc.osl.blocks.impl.mixin.common; + +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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.block.Block; + +import net.ornithemc.osl.blocks.api.BlockRegistry; +import net.ornithemc.osl.blocks.api.block.BlockExtension; +import net.ornithemc.osl.blocks.impl.BlockRegistryImpl; +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.impl.util.Util; + +@Mixin(Block.class) +public class BlockMixin implements BlockExtension { + + @Shadow + private String key; + + @Inject( + method = "init", + at = @At( + value = "HEAD" + ) + ) + private static void osl$blocks$unlockBlockRegistry(CallbackInfo ci) { + BlockRegistryImpl.unlock(); + } + + @Inject( + method = "init", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/util/registry/DefaultedIdRegistry;validate()V" + ) + ) + private static void osl$blocks$registerBlocks(CallbackInfo ci) { + BlockRegistryImpl.registerBlocks(); + } + + @Inject( + method = "getTranslationKey", + at = @At( + value = "HEAD" + ) + ) + private void osl$blocks$autoAssignTranslationKey(CallbackInfoReturnable cir) { + if (this.key == null) { + NamespacedIdentifier identifier = BlockRegistry.getIdentifier((Block) (Object) this); + + if (identifier == null) { + this.key = "unknown"; + } else { + this.key = Util.makeTranslationKey(identifier); + } + } + } + + @Override + public boolean isAir() { + return false; + } +} diff --git a/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/StatsMixin.java b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/StatsMixin.java new file mode 100644 index 000000000..019e93566 --- /dev/null +++ b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/StatsMixin.java @@ -0,0 +1,34 @@ +package net.ornithemc.osl.blocks.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.stat.Stat; +import net.minecraft.stat.Stats; + +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.ObjectArrayMapper; + +@Mixin(Stats.class) +public class StatsMixin { + + @Shadow @Final + private static Stat[] BLOCKS_MINED; + + @Inject( + // inject at init instead of in case the arrays are resized... + method = "init", + at = @At( + value = "TAIL" + ) + ) + private static void osl$items$registerStatsMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("stats/mined"), ObjectArrayMapper.of(BLOCKS_MINED)); + } +} diff --git a/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/resources/fabric.mod.json b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/resources/fabric.mod.json similarity index 50% rename from libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/resources/fabric.mod.json rename to libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/resources/fabric.mod.json index f5e589d41..77669c32f 100644 --- a/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/resources/fabric.mod.json +++ b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/resources/fabric.mod.json @@ -1,16 +1,28 @@ { "schemaVersion": 1, "id": "osl-blocks", - "version": "0.1.1+mc14w27a-mc17w46a", + "version": "0.1.1+mc15w36a-mc17w46a", "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.blocks.impl.BlockRegistryImpl::init" + ] + }, "mixins": [ "osl.blocks.mixins.json" ], "accessWidener": "osl.blocks.classtweaker", "depends": { "fabricloader": "\u003e\u003d0.18.0", - "minecraft": "\u003e\u003d1.8-alpha.14.27.a \u003c\u003d1.13-alpha.17.46.a", - "osl-core": "\u003e\u003d0.9.0" + "minecraft": "\u003e\u003d1.9-alpha.15.36.a \u003c\u003d1.13-alpha.17.46.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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0", + "osl-registries": "\u003e\u003d0.1.0-" }, "name": "OSL Blocks", "description": "Blocks API and events.", diff --git a/libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/resources/osl.blocks.classtweaker b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/resources/osl.blocks.classtweaker similarity index 100% rename from libraries/blocks/blocks-mc14w27a-mc17w46a/src/main/resources/osl.blocks.classtweaker rename to libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/resources/osl.blocks.classtweaker diff --git a/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/resources/osl.blocks.mixins.json b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/resources/osl.blocks.mixins.json new file mode 100644 index 000000000..ff43e2f92 --- /dev/null +++ b/libraries/blocks/blocks-mc15w36a-mc17w46a/src/main/resources/osl.blocks.mixins.json @@ -0,0 +1,20 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.blocks.impl.mixin", + "compatibilityLevel": "JAVA_8", + "plugin": "net.ornithemc.osl.blocks.impl.BlocksMixinPlugin", + "mixins": [ + "common.AirBlockMixin", + "common.BlockMixin", + "common.StatsMixin" + ], + "client": [ + "client.BlockColorsMixin" + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java b/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java index 96500cd94..0f196b50e 100644 --- a/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java +++ b/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java @@ -6,12 +6,16 @@ import net.ornithemc.osl.blocks.impl.BlockRegistryImpl; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; /** * Public access to the Blocks registry. */ public final class BlockRegistry { + public static final DefaultedRegistry REGISTRY = BlockRegistryImpl.REGISTRY; + /** * @return the numerical ID assigned to the given block. */ @@ -22,7 +26,14 @@ public static int getId(Block block) { /** * @return the namespaced ID assigned to the given block. */ - public static NamespacedIdentifier getKey(Block block) { + public static NamespacedIdentifier getIdentifier(Block block) { + return BlockRegistryImpl.getIdentifier(block); + } + + /** + * @return the resource key assigned to the given block. + */ + public static ResourceKey getKey(Block block) { return BlockRegistryImpl.getKey(block); } @@ -36,24 +47,48 @@ public static Block getBlock(int id) { /** * @return the block mapped to the given namespaced ID. */ - public static Block getBlock(NamespacedIdentifier key) { + public static Block getBlock(NamespacedIdentifier identifier) { + return BlockRegistryImpl.getBlock(identifier); + } + + /** + * @return the block mapped to the given resource key. + */ + public static Block getBlock(ResourceKey key) { return BlockRegistryImpl.getBlock(key); } /** * @return a set containing all namespaced IDs in the registry. */ - public static Set keySet() { + public static Set identifierSet() { + return BlockRegistryImpl.identifierSet(); + } + + /** + * @return a set containing all resource keys in the registry. + */ + public static Set> keySet() { return BlockRegistryImpl.keySet(); } + /** + * @param the block type. + * @param identifier the namespaced ID of the block. + * @param block the block to register. + * @return the registered block. + */ + public static T register(NamespacedIdentifier identifier, T block) { + return BlockRegistryImpl.register(identifier, block); + } + /** * @param the block type. - * @param key the namespaced ID of the block. + * @param key the resource key of the block. * @param block the block to register. * @return the registered block. */ - public static T register(NamespacedIdentifier key, T block) { + public static T register(ResourceKey key, T block) { return BlockRegistryImpl.register(key, block); } } diff --git a/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java b/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java index 3f168bd4e..f4466ec4b 100644 --- a/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java +++ b/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java @@ -1,75 +1,84 @@ package net.ornithemc.osl.blocks.impl; -import java.util.Collections; import java.util.Set; import net.minecraft.block.Block; -import net.minecraft.resource.Identifier; import net.ornithemc.osl.blocks.api.BlockEvents; +import net.ornithemc.osl.blocks.impl.block.BlockStateRegistryFixer; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +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 BlockRegistryImpl { + public static final DefaultedRegistry REGISTRY = VanillaRegistries.registerDefaulted(RegistryKeys.BLOCK, Block.REGISTRY); + private static boolean locked = true; - private static boolean initialized = false; public static int getId(Block block) { - return Block.REGISTRY.getId(block); + return REGISTRY.getId(block); + } + + public static NamespacedIdentifier getIdentifier(Block block) { + return REGISTRY.getIdentifier(block); } - public static NamespacedIdentifier getKey(Block block) { - return Block.REGISTRY.getKey(block); + public static ResourceKey getKey(Block block) { + return REGISTRY.getKey(block); } public static Block getBlock(int id) { - return Block.REGISTRY.get(id); + return REGISTRY.get(id); } - public static Block getBlock(NamespacedIdentifier key) { - return Block.REGISTRY.get(identifier(key)); + public static Block getBlock(NamespacedIdentifier identifier) { + return REGISTRY.get(identifier); } - public static Set keySet() { - return Collections.unmodifiableSet(Block.REGISTRY.entrySet()); + public static Block getBlock(ResourceKey key) { + return REGISTRY.get(key); } - public static T register(NamespacedIdentifier key, T block) { - if (locked) { - throw new IllegalStateException("register called too " + (initialized ? "late" : "early") + ": registry locked!"); - } else { - Block.REGISTRY.put(identifier(key), block); - } + public static Set identifierSet() { + return REGISTRY.identifierSet(); + } - return block; + public static Set> keySet() { + return REGISTRY.keySet(); } - private static Identifier identifier(NamespacedIdentifier id) { - return id instanceof Identifier ? (Identifier) id : new Identifier(id.namespace(), id.identifier()); + public static T register(NamespacedIdentifier identifier, T block) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, identifier, block); + } } - public static void lock() { - if (!initialized) { - throw new IllegalStateException("cannot lock block registry unless it's been initialized!"); + public static T register(ResourceKey key, T block) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, key, block); } + } - locked = true; + public static void init() { + SyncedRegistries.register(RegistryKeys.BLOCK); + SyncedRegistries.registerFixer(RegistryKeys.BLOCK, NamespacedIdentifiers.from("blockstate"), new BlockStateRegistryFixer()); } public static void unlock() { - if (initialized) { - throw new IllegalStateException("cannot unlock block registry once it's been initialized!"); - } - locked = false; } - public static void init() { - if (locked) { - throw new IllegalStateException("cannot initialize block registry when it's locked!"); - } - + public static void registerBlocks() { BlockEvents.REGISTER_BLOCKS.invoker().run(); - initialized = true; } } diff --git a/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockStateRegistryFixer.java b/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockStateRegistryFixer.java new file mode 100644 index 000000000..97a1f2372 --- /dev/null +++ b/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockStateRegistryFixer.java @@ -0,0 +1,22 @@ +package net.ornithemc.osl.blocks.impl.block; + +import net.minecraft.block.Block; +import net.minecraft.block.state.BlockState; + +import net.ornithemc.osl.blocks.api.BlockRegistry; +import net.ornithemc.osl.registries.api.registry.sync.IdFixer; +import net.ornithemc.osl.registries.impl.access.Clearable; + +public class BlockStateRegistryFixer implements IdFixer { + + @Override + public void apply() { + Clearable.clear(Block.STATE_REGISTRY); + + for (Block block : BlockRegistry.REGISTRY) { + for (BlockState state : block.stateDefinition().all()) { + Block.STATE_REGISTRY.put(state); + } + } + } +} diff --git a/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/client/BlockColorsMixin.java b/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/client/BlockColorsMixin.java new file mode 100644 index 000000000..4cb0a6c32 --- /dev/null +++ b/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/client/BlockColorsMixin.java @@ -0,0 +1,34 @@ +package net.ornithemc.osl.blocks.impl.mixin.client; + +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.client.world.color.BlockColor; +import net.minecraft.client.world.color.BlockColors; +import net.minecraft.util.Id2ObjectBiMap; + +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(BlockColors.class) +public class BlockColorsMixin { + + @Shadow @Final + private Id2ObjectBiMap registry; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$registerModelRegistryMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block_color"), Id2ObjectBiMapMapper.of(this.registry)); + } +} diff --git a/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java b/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java index 17924f839..c873c42c5 100644 --- a/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java +++ b/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java @@ -38,8 +38,7 @@ public class BlockMixin { shift = Shift.AFTER ) ) - private static void osl$blocks$initAndLockBlockRegistry(CallbackInfo ci) { - BlockRegistryImpl.init(); - BlockRegistryImpl.lock(); + private static void osl$blocks$registerBlocks(CallbackInfo ci) { + BlockRegistryImpl.registerBlocks(); } } diff --git a/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/resources/fabric.mod.json b/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/resources/fabric.mod.json index d20c30df3..d9c99a844 100644 --- a/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/resources/fabric.mod.json +++ b/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/resources/fabric.mod.json @@ -3,13 +3,25 @@ "id": "osl-blocks", "version": "0.1.1+mc17w47a-mc18w31a", "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.blocks.impl.BlockRegistryImpl::init" + ] + }, "mixins": [ "osl.blocks.mixins.json" ], "depends": { "fabricloader": "\u003e\u003d0.18.0", "minecraft": "\u003e\u003d1.13-alpha.17.47.a \u003c\u003d1.13.1-alpha.18.31.a", - "osl-core": "\u003e\u003d0.9.0" + "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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0", + "osl-registries": "\u003e\u003d0.1.0-" }, "name": "OSL Blocks", "description": "Blocks API and events.", diff --git a/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/resources/osl.blocks.mixins.json b/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/resources/osl.blocks.mixins.json index bfd6b26fa..afa7739ac 100644 --- a/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/resources/osl.blocks.mixins.json +++ b/libraries/blocks/blocks-mc17w47a-mc18w31a/src/main/resources/osl.blocks.mixins.json @@ -7,6 +7,7 @@ "common.BlockMixin" ], "client": [ + "client.BlockColorsMixin" ], "server": [ ], diff --git a/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java b/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java index 96500cd94..0f196b50e 100644 --- a/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java +++ b/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java @@ -6,12 +6,16 @@ import net.ornithemc.osl.blocks.impl.BlockRegistryImpl; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; /** * Public access to the Blocks registry. */ public final class BlockRegistry { + public static final DefaultedRegistry REGISTRY = BlockRegistryImpl.REGISTRY; + /** * @return the numerical ID assigned to the given block. */ @@ -22,7 +26,14 @@ public static int getId(Block block) { /** * @return the namespaced ID assigned to the given block. */ - public static NamespacedIdentifier getKey(Block block) { + public static NamespacedIdentifier getIdentifier(Block block) { + return BlockRegistryImpl.getIdentifier(block); + } + + /** + * @return the resource key assigned to the given block. + */ + public static ResourceKey getKey(Block block) { return BlockRegistryImpl.getKey(block); } @@ -36,24 +47,48 @@ public static Block getBlock(int id) { /** * @return the block mapped to the given namespaced ID. */ - public static Block getBlock(NamespacedIdentifier key) { + public static Block getBlock(NamespacedIdentifier identifier) { + return BlockRegistryImpl.getBlock(identifier); + } + + /** + * @return the block mapped to the given resource key. + */ + public static Block getBlock(ResourceKey key) { return BlockRegistryImpl.getBlock(key); } /** * @return a set containing all namespaced IDs in the registry. */ - public static Set keySet() { + public static Set identifierSet() { + return BlockRegistryImpl.identifierSet(); + } + + /** + * @return a set containing all resource keys in the registry. + */ + public static Set> keySet() { return BlockRegistryImpl.keySet(); } + /** + * @param the block type. + * @param identifier the namespaced ID of the block. + * @param block the block to register. + * @return the registered block. + */ + public static T register(NamespacedIdentifier identifier, T block) { + return BlockRegistryImpl.register(identifier, block); + } + /** * @param the block type. - * @param key the namespaced ID of the block. + * @param key the resource key of the block. * @param block the block to register. * @return the registered block. */ - public static T register(NamespacedIdentifier key, T block) { + public static T register(ResourceKey key, T block) { return BlockRegistryImpl.register(key, block); } } diff --git a/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java b/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java index 374e98f77..82b8d9436 100644 --- a/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java +++ b/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java @@ -1,76 +1,84 @@ package net.ornithemc.osl.blocks.impl; -import java.util.Collections; import java.util.Set; import net.minecraft.block.Block; -import net.minecraft.resource.Identifier; -import net.minecraft.util.registry.Registry; import net.ornithemc.osl.blocks.api.BlockEvents; +import net.ornithemc.osl.blocks.impl.block.BlockStateRegistryFixer; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +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 BlockRegistryImpl { + public static final DefaultedRegistry REGISTRY = VanillaRegistries.registerDefaulted(RegistryKeys.BLOCK, net.minecraft.util.registry.Registry.BLOCK); + private static boolean locked = true; - private static boolean initialized = false; public static int getId(Block block) { - return Registry.BLOCK.getId(block); + return REGISTRY.getId(block); + } + + public static NamespacedIdentifier getIdentifier(Block block) { + return REGISTRY.getIdentifier(block); } - public static NamespacedIdentifier getKey(Block block) { - return Registry.BLOCK.getKey(block); + public static ResourceKey getKey(Block block) { + return REGISTRY.getKey(block); } public static Block getBlock(int id) { - return Registry.BLOCK.get(id); + return REGISTRY.get(id); } - public static Block getBlock(NamespacedIdentifier key) { - return Registry.BLOCK.get(identifier(key)); + public static Block getBlock(NamespacedIdentifier identifier) { + return REGISTRY.get(identifier); } - public static Set keySet() { - return Collections.unmodifiableSet(Registry.BLOCK.keySet()); + public static Block getBlock(ResourceKey key) { + return REGISTRY.get(key); } - public static T register(NamespacedIdentifier key, T block) { - if (locked) { - throw new IllegalStateException("register called too " + (initialized ? "late" : "early") + ": registry locked!"); - } else { - Registry.BLOCK.register(identifier(key), block); - } + public static Set identifierSet() { + return REGISTRY.identifierSet(); + } - return block; + public static Set> keySet() { + return REGISTRY.keySet(); } - private static Identifier identifier(NamespacedIdentifier id) { - return id instanceof Identifier ? (Identifier) id : new Identifier(id.namespace(), id.identifier()); + public static T register(NamespacedIdentifier identifier, T block) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, identifier, block); + } } - public static void lock() { - if (!initialized) { - throw new IllegalStateException("cannot lock block registry unless it's been initialized!"); + public static T register(ResourceKey key, T block) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, key, block); } + } - locked = true; + public static void init() { + SyncedRegistries.register(RegistryKeys.BLOCK); + SyncedRegistries.registerFixer(RegistryKeys.BLOCK, NamespacedIdentifiers.from("blockstate"), new BlockStateRegistryFixer()); } public static void unlock() { - if (initialized) { - throw new IllegalStateException("cannot unlock block registry once it's been initialized!"); - } - locked = false; } - public static void init() { - if (locked) { - throw new IllegalStateException("cannot initialize block registry when it's locked!"); - } - + public static void registerBlocks() { BlockEvents.REGISTER_BLOCKS.invoker().run(); - initialized = true; } } diff --git a/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockStateRegistryFixer.java b/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockStateRegistryFixer.java new file mode 100644 index 000000000..97a1f2372 --- /dev/null +++ b/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockStateRegistryFixer.java @@ -0,0 +1,22 @@ +package net.ornithemc.osl.blocks.impl.block; + +import net.minecraft.block.Block; +import net.minecraft.block.state.BlockState; + +import net.ornithemc.osl.blocks.api.BlockRegistry; +import net.ornithemc.osl.registries.api.registry.sync.IdFixer; +import net.ornithemc.osl.registries.impl.access.Clearable; + +public class BlockStateRegistryFixer implements IdFixer { + + @Override + public void apply() { + Clearable.clear(Block.STATE_REGISTRY); + + for (Block block : BlockRegistry.REGISTRY) { + for (BlockState state : block.stateDefinition().all()) { + Block.STATE_REGISTRY.put(state); + } + } + } +} diff --git a/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/impl/mixin/client/BlockColorsMixin.java b/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/impl/mixin/client/BlockColorsMixin.java new file mode 100644 index 000000000..4cb0a6c32 --- /dev/null +++ b/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/impl/mixin/client/BlockColorsMixin.java @@ -0,0 +1,34 @@ +package net.ornithemc.osl.blocks.impl.mixin.client; + +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.client.world.color.BlockColor; +import net.minecraft.client.world.color.BlockColors; +import net.minecraft.util.Id2ObjectBiMap; + +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(BlockColors.class) +public class BlockColorsMixin { + + @Shadow @Final + private Id2ObjectBiMap registry; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$registerModelRegistryMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block_color"), Id2ObjectBiMapMapper.of(this.registry)); + } +} diff --git a/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java b/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java index 17924f839..c873c42c5 100644 --- a/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java +++ b/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java @@ -38,8 +38,7 @@ public class BlockMixin { shift = Shift.AFTER ) ) - private static void osl$blocks$initAndLockBlockRegistry(CallbackInfo ci) { - BlockRegistryImpl.init(); - BlockRegistryImpl.lock(); + private static void osl$blocks$registerBlocks(CallbackInfo ci) { + BlockRegistryImpl.registerBlocks(); } } diff --git a/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json b/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json index 5ea18e8d0..1f0dd16be 100644 --- a/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json +++ b/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json @@ -3,13 +3,25 @@ "id": "osl-blocks", "version": "0.1.1+mc18w32a-mc1.13.2", "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.blocks.impl.BlockRegistryImpl::init" + ] + }, "mixins": [ "osl.blocks.mixins.json" ], "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-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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0", + "osl-registries": "\u003e\u003d0.1.0-" }, "name": "OSL Blocks", "description": "Blocks API and events.", diff --git a/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/resources/osl.blocks.mixins.json b/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/resources/osl.blocks.mixins.json index bfd6b26fa..afa7739ac 100644 --- a/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/resources/osl.blocks.mixins.json +++ b/libraries/blocks/blocks-mc18w32a-mc1.13.2/src/main/resources/osl.blocks.mixins.json @@ -7,6 +7,7 @@ "common.BlockMixin" ], "client": [ + "client.BlockColorsMixin" ], "server": [ ], diff --git a/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java b/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java index 96500cd94..0f196b50e 100644 --- a/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java +++ b/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java @@ -6,12 +6,16 @@ import net.ornithemc.osl.blocks.impl.BlockRegistryImpl; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; /** * Public access to the Blocks registry. */ public final class BlockRegistry { + public static final DefaultedRegistry REGISTRY = BlockRegistryImpl.REGISTRY; + /** * @return the numerical ID assigned to the given block. */ @@ -22,7 +26,14 @@ public static int getId(Block block) { /** * @return the namespaced ID assigned to the given block. */ - public static NamespacedIdentifier getKey(Block block) { + public static NamespacedIdentifier getIdentifier(Block block) { + return BlockRegistryImpl.getIdentifier(block); + } + + /** + * @return the resource key assigned to the given block. + */ + public static ResourceKey getKey(Block block) { return BlockRegistryImpl.getKey(block); } @@ -36,24 +47,48 @@ public static Block getBlock(int id) { /** * @return the block mapped to the given namespaced ID. */ - public static Block getBlock(NamespacedIdentifier key) { + public static Block getBlock(NamespacedIdentifier identifier) { + return BlockRegistryImpl.getBlock(identifier); + } + + /** + * @return the block mapped to the given resource key. + */ + public static Block getBlock(ResourceKey key) { return BlockRegistryImpl.getBlock(key); } /** * @return a set containing all namespaced IDs in the registry. */ - public static Set keySet() { + public static Set identifierSet() { + return BlockRegistryImpl.identifierSet(); + } + + /** + * @return a set containing all resource keys in the registry. + */ + public static Set> keySet() { return BlockRegistryImpl.keySet(); } + /** + * @param the block type. + * @param identifier the namespaced ID of the block. + * @param block the block to register. + * @return the registered block. + */ + public static T register(NamespacedIdentifier identifier, T block) { + return BlockRegistryImpl.register(identifier, block); + } + /** * @param the block type. - * @param key the namespaced ID of the block. + * @param key the resource key of the block. * @param block the block to register. * @return the registered block. */ - public static T register(NamespacedIdentifier key, T block) { + public static T register(ResourceKey key, T block) { return BlockRegistryImpl.register(key, block); } } diff --git a/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java b/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java index 790b4b721..82b8d9436 100644 --- a/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java +++ b/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java @@ -1,74 +1,84 @@ package net.ornithemc.osl.blocks.impl; -import java.util.Collections; import java.util.Set; import net.minecraft.block.Block; -import net.minecraft.resource.Identifier; -import net.minecraft.util.registry.Registry; import net.ornithemc.osl.blocks.api.BlockEvents; +import net.ornithemc.osl.blocks.impl.block.BlockStateRegistryFixer; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +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 BlockRegistryImpl { + public static final DefaultedRegistry REGISTRY = VanillaRegistries.registerDefaulted(RegistryKeys.BLOCK, net.minecraft.util.registry.Registry.BLOCK); + private static boolean locked = true; - private static boolean initialized = false; public static int getId(Block block) { - return Registry.BLOCK.getId(block); + return REGISTRY.getId(block); + } + + public static NamespacedIdentifier getIdentifier(Block block) { + return REGISTRY.getIdentifier(block); } - public static NamespacedIdentifier getKey(Block block) { - return Registry.BLOCK.getKey(block); + public static ResourceKey getKey(Block block) { + return REGISTRY.getKey(block); } public static Block getBlock(int id) { - return Registry.BLOCK.get(id); + return REGISTRY.get(id); + } + + public static Block getBlock(NamespacedIdentifier identifier) { + return REGISTRY.get(identifier); } - public static Block getBlock(NamespacedIdentifier key) { - return Registry.BLOCK.getOrDefault(identifier(key)); + public static Block getBlock(ResourceKey key) { + return REGISTRY.get(key); } - public static Set keySet() { - return Collections.unmodifiableSet(Registry.BLOCK.keySet()); + public static Set identifierSet() { + return REGISTRY.identifierSet(); } - public static T register(NamespacedIdentifier key, T block) { + public static Set> keySet() { + return REGISTRY.keySet(); + } + + public static T register(NamespacedIdentifier identifier, T block) { if (locked) { - throw new IllegalStateException("register called too " + (initialized ? "late" : "early") + ": registry locked!"); + throw new IllegalStateException("register called too early: registry locked!"); } else { - return Registry.BLOCK.m_30368144(identifier(key), block); + return Registry.register(REGISTRY, identifier, block); } } - private static Identifier identifier(NamespacedIdentifier id) { - return id instanceof Identifier ? (Identifier) id : new Identifier(id.namespace(), id.identifier()); - } - - public static void lock() { - if (!initialized) { - throw new IllegalStateException("cannot lock block registry unless it's been initialized!"); + public static T register(ResourceKey key, T block) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, key, block); } + } - locked = true; + public static void init() { + SyncedRegistries.register(RegistryKeys.BLOCK); + SyncedRegistries.registerFixer(RegistryKeys.BLOCK, NamespacedIdentifiers.from("blockstate"), new BlockStateRegistryFixer()); } public static void unlock() { - if (initialized) { - throw new IllegalStateException("cannot unlock block registry once it's been initialized!"); - } - locked = false; } - public static void init() { - if (locked) { - throw new IllegalStateException("cannot initialize block registry when it's locked!"); - } - + public static void registerBlocks() { BlockEvents.REGISTER_BLOCKS.invoker().run(); - initialized = true; } } diff --git a/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockStateRegistryFixer.java b/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockStateRegistryFixer.java new file mode 100644 index 000000000..97a1f2372 --- /dev/null +++ b/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockStateRegistryFixer.java @@ -0,0 +1,22 @@ +package net.ornithemc.osl.blocks.impl.block; + +import net.minecraft.block.Block; +import net.minecraft.block.state.BlockState; + +import net.ornithemc.osl.blocks.api.BlockRegistry; +import net.ornithemc.osl.registries.api.registry.sync.IdFixer; +import net.ornithemc.osl.registries.impl.access.Clearable; + +public class BlockStateRegistryFixer implements IdFixer { + + @Override + public void apply() { + Clearable.clear(Block.STATE_REGISTRY); + + for (Block block : BlockRegistry.REGISTRY) { + for (BlockState state : block.stateDefinition().all()) { + Block.STATE_REGISTRY.put(state); + } + } + } +} diff --git a/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/client/BlockColorsMixin.java b/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/client/BlockColorsMixin.java new file mode 100644 index 000000000..4cb0a6c32 --- /dev/null +++ b/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/client/BlockColorsMixin.java @@ -0,0 +1,34 @@ +package net.ornithemc.osl.blocks.impl.mixin.client; + +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.client.world.color.BlockColor; +import net.minecraft.client.world.color.BlockColors; +import net.minecraft.util.Id2ObjectBiMap; + +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(BlockColors.class) +public class BlockColorsMixin { + + @Shadow @Final + private Id2ObjectBiMap registry; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$registerModelRegistryMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block_color"), Id2ObjectBiMapMapper.of(this.registry)); + } +} diff --git a/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlocksMixin.java b/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlocksMixin.java index 27b3d23c0..608abdb99 100644 --- a/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlocksMixin.java +++ b/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlocksMixin.java @@ -29,8 +29,7 @@ public class BlocksMixin { target = "Lnet/minecraft/util/registry/Registry;BLOCK:Lnet/minecraft/util/registry/DefaultedIdRegistry;" ) ) - private static void osl$blocks$initAndLockBlockRegistry(CallbackInfo ci) { - BlockRegistryImpl.init(); - BlockRegistryImpl.lock(); + private static void osl$blocks$registerBlocks(CallbackInfo ci) { + BlockRegistryImpl.registerBlocks(); } } diff --git a/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json b/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json index 110b40cd9..7dbbc4da5 100644 --- a/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json +++ b/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json @@ -3,13 +3,25 @@ "id": "osl-blocks", "version": "0.1.1+mc18w43a-mc1.14.4", "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.blocks.impl.BlockRegistryImpl::init" + ] + }, "mixins": [ "osl.blocks.mixins.json" ], "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-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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0", + "osl-registries": "\u003e\u003d0.1.0-" }, "name": "OSL Blocks", "description": "Blocks API and events.", diff --git a/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/resources/osl.blocks.mixins.json b/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/resources/osl.blocks.mixins.json index c958d77d3..9ab75017c 100644 --- a/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/resources/osl.blocks.mixins.json +++ b/libraries/blocks/blocks-mc18w43a-mc1.14.4/src/main/resources/osl.blocks.mixins.json @@ -7,6 +7,7 @@ "common.BlocksMixin" ], "client": [ + "client.BlockColorsMixin" ], "server": [ ], diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java index 003e6ec54..ae6522ef9 100644 --- a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/api/BlockRegistry.java @@ -6,12 +6,16 @@ import net.ornithemc.osl.blocks.impl.BlockRegistryImpl; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; /** * Public access to the Blocks registry. */ public final class BlockRegistry { + public static final DefaultedRegistry REGISTRY = BlockRegistryImpl.REGISTRY; + /** * @return the numerical ID assigned to the given block. */ @@ -22,7 +26,14 @@ public static int getId(Block block) { /** * @return the namespaced ID assigned to the given block. */ - public static NamespacedIdentifier getKey(Block block) { + public static NamespacedIdentifier getIdentifier(Block block) { + return BlockRegistryImpl.getIdentifier(block); + } + + /** + * @return the resource key assigned to the given block. + */ + public static ResourceKey getKey(Block block) { return BlockRegistryImpl.getKey(block); } @@ -36,24 +47,62 @@ public static Block getBlock(int id) { /** * @return the block mapped to the given namespaced ID. */ - public static Block getBlock(NamespacedIdentifier key) { + public static Block getBlock(NamespacedIdentifier identifier) { + return BlockRegistryImpl.getBlock(identifier); + } + + /** + * @return the block mapped to the given resource key. + */ + public static Block getBlock(ResourceKey key) { return BlockRegistryImpl.getBlock(key); } /** * @return a set containing all namespaced IDs in the registry. */ - public static Set keySet() { + public static Set identifierSet() { + return BlockRegistryImpl.identifierSet(); + } + + /** + * @return a set containing all resource keys in the registry. + */ + public static Set> keySet() { return BlockRegistryImpl.keySet(); } + /** + * @param the block type. + * @param identifier the namespaced ID of the block. + * @param block the block to register. + * @return the registered block. + */ + public static T register(NamespacedIdentifier identifier, T block) { + return BlockRegistryImpl.register(identifier, block); + } + + /** + * @param the block type. + * @param key the resource key of the block. + * @param block the block to register. + * @return the registered block. + */ + public static T register(ResourceKey key, T block) { + return BlockRegistryImpl.register(key, block); + } + /** * @param the block type. * @param id the numerical ID of the block. * @param key the namespaced ID of the block. * @param block the block to register. * @return the registered block. + * + * @deprecated use {@linkplain #register(NamespacedIdentifier, Block)} + * or {@linkplain #register(ResourceKey, Block)} instead. */ + @Deprecated public static T register(int id, NamespacedIdentifier key, T block) { return BlockRegistryImpl.register(id, key, block); } diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/api/block/BlockExtension.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/api/block/BlockExtension.java index 152e77faa..8d70e623b 100644 --- a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/api/block/BlockExtension.java +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/api/block/BlockExtension.java @@ -2,12 +2,13 @@ import net.minecraft.block.Block; -import net.ornithemc.osl.core.api.registry.DefaultedIdRegistry; -import net.ornithemc.osl.core.api.registry.SimpleIdRegistry; +import net.ornithemc.osl.blocks.impl.BlockRegistryImpl; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; public interface BlockExtension { - SimpleIdRegistry REGISTRY = new DefaultedIdRegistry<>("air"); + DefaultedRegistry REGISTRY = BlockRegistryImpl.REGISTRY; + int AUTO_ASSIGN_ID = -172; /** * @return whether this block is air. diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java index d3e4dee39..2d48ebc18 100644 --- a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/BlockRegistryImpl.java @@ -5,67 +5,108 @@ import net.minecraft.block.Block; import net.ornithemc.osl.blocks.api.BlockEvents; +import net.ornithemc.osl.blocks.impl.block.BlockIdFixer; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +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 BlockRegistryImpl { + public static final DefaultedRegistry REGISTRY = Registries.registerDefaulted(RegistryKeys.BLOCK, NamespacedIdentifiers.from("air"), () -> Block.BY_ID.getClass()); + private static boolean locked = true; - private static boolean initialized = false; public static int getId(Block block) { - return Block.REGISTRY.getId(block); + return REGISTRY.getId(block); + } + + public static NamespacedIdentifier getIdentifier(Block block) { + return REGISTRY.getIdentifier(block); } - public static NamespacedIdentifier getKey(Block block) { - return Block.REGISTRY.getKey(block); + public static ResourceKey getKey(Block block) { + return REGISTRY.getKey(block); } public static Block getBlock(int id) { - return Block.REGISTRY.get(id); + return REGISTRY.get(id); } - public static Block getBlock(NamespacedIdentifier key) { - return Block.REGISTRY.get(key); + public static Block getBlock(NamespacedIdentifier identifier) { + return REGISTRY.get(identifier); } - public static Set keySet() { - return Block.REGISTRY.keySet(); + public static Block getBlock(ResourceKey key) { + return REGISTRY.get(key); } - public static T register(int id, NamespacedIdentifier key, T block) { + public static Set identifierSet() { + return REGISTRY.identifierSet(); + } + + public static Set> keySet() { + return REGISTRY.keySet(); + } + + @SuppressWarnings("deprecation") + public static T register(NamespacedIdentifier identifier, T block) { if (locked) { - throw new IllegalStateException("register called too " + (initialized ? "late" : "early") + ": registry locked!"); + throw new IllegalStateException("register called too early: registry locked!"); } else { - Block.REGISTRY.register(id, key, block); + return Registry.register(REGISTRY, block.id, identifier, block); } + } - return block; + @SuppressWarnings("deprecation") + public static T register(ResourceKey key, T block) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, block.id, key, block); + } } - public static void lock() { - if (!initialized) { - throw new IllegalStateException("cannot lock block registry unless it's been initialized!"); + @Deprecated + public static T register(int id, NamespacedIdentifier key, T block) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + if (block.id != id) { + throw new IllegalArgumentException("ID " + id + " does not match block ID " + block.id + " for " + key); + } + + return Registry.register(REGISTRY, id, key, block); } + } - locked = true; + public static void init() { + SyncedRegistries.register(RegistryKeys.BLOCK); + SyncedRegistries.registerFixer(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block/id"), new BlockIdFixer()); } public static void unlock() { - if (initialized) { - throw new IllegalStateException("cannot unlock block registry once it's been initialized!"); - } - locked = false; } - public static void init() { - if (locked) { - throw new IllegalStateException("cannot initialize block registry when it's locked!"); - } - + public static void registerBlocks() { VanillaBlocks.init(); - BlockEvents.REGISTER_BLOCKS.invoker().run(); - initialized = true; + } + + public static void registerUnknownBlocks() { + for (Block block : Block.BY_ID) { + if (block != null && block.id != 0 && REGISTRY.getIdentifier(block) == REGISTRY.getDefaultIdentifier()) { + NamespacedIdentifier identifier = NamespacedIdentifiers.from("osl", "block_" + block.id); + + RegistriesImpl.LOGGER.warn("Block {}/{}", block.id, block.getClass().getSimpleName() + " was not registered to OSL's Block registry! Adding it as '" + identifier + "'..."); + BlockRegistryImpl.register(identifier, block); + } + } } } diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/BlocksMixinPlugin.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/BlocksMixinPlugin.java index 8b15e1628..1cd18f87c 100644 --- a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/BlocksMixinPlugin.java +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/BlocksMixinPlugin.java @@ -8,10 +8,14 @@ import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; +import net.fabricmc.api.EnvType; +import net.fabricmc.loader.api.FabricLoader; + import net.ornithemc.osl.core.impl.util.MinecraftVersion; public class BlocksMixinPlugin implements IMixinConfigPlugin { + public static final boolean CLIENT_SIDE = FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT; public static final boolean BLOCK_IS_METHOD_PRESENT = MinecraftVersion.resolve().compareTo("13w01a") >= 0; @Override @@ -37,9 +41,39 @@ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { if ("net.ornithemc.osl.blocks.impl.mixin.common.RepeaterBlockMixin".equals(mixinClassName)) { return !BLOCK_IS_METHOD_PRESENT && MinecraftVersion.resolve().compareTo("b1.3") >= 0; } + if ("net.ornithemc.osl.blocks.impl.mixin.common.BlockMixin_1_3_1_13w01a".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("1.3.1") >= 0 && MinecraftVersion.resolve().compareTo("13w01a") <= 0; + } + if ("net.ornithemc.osl.blocks.impl.mixin.common.BlockMixin_12w06a".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("12w06a") <= 0; + } + if ("net.ornithemc.osl.blocks.impl.mixin.common.BlockMixin_12w40a".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("12w40a") >= 0; + } + if ("net.ornithemc.osl.blocks.impl.mixin.common.BlockMixin_13w02a".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("13w02a") >= 0; + } + if ("net.ornithemc.osl.blocks.impl.mixin.common.BlockMixin_a1_1_0_12w06a".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo(CLIENT_SIDE ? "a1.1.0" : "a0.2.0") >= 0 && MinecraftVersion.resolve().compareTo("12w06a") <= 0; + } + if ("net.ornithemc.osl.blocks.impl.mixin.common.BlockMixin_b1_0_1_3".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("b1.0") >= 0 && MinecraftVersion.resolve().compareTo("1.3") <= 0; + } + if ("net.ornithemc.osl.blocks.impl.mixin.common.BlockMixin_b1_6_tb3_1_4_7".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("b1.6-tb3") >= 0 && MinecraftVersion.resolve().compareTo("1.4.7") <= 0; + } + if ("net.ornithemc.osl.blocks.impl.mixin.common.BlockMixin_b1_9_pre5_12w38b".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("b1.9-pre5") >= 0 && MinecraftVersion.resolve().compareTo("12w38b") <= 0; + } if ("net.ornithemc.osl.blocks.impl.mixin.common.WorldMixin".equals(mixinClassName)) { return MinecraftVersion.resolve().compareTo("12w03a") <= 0; } + if ("net.ornithemc.osl.blocks.impl.mixin.common.EndermanEntityMixin".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("b1.8") >= 0; + } + if ("net.ornithemc.osl.blocks.impl.mixin.common.StatsMixin".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("b1.4") >= 0; + } return true; } diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/VanillaBlocks.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/VanillaBlocks.java index b5f66e7ac..51c098c68 100644 --- a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/VanillaBlocks.java +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/VanillaBlocks.java @@ -8,7 +8,7 @@ import net.ornithemc.osl.blocks.api.block.Blocks; import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; -final class VanillaBlocks { +public final class VanillaBlocks { /** * Namespaced IDs were introduced in 1.7. Before then, the numerical IDs @@ -215,6 +215,8 @@ final class VanillaBlocks { "coal_block" }; + public static final int MAX_ID = 255; + static void init() { // Air block added by OSL register(Blocks.AIR); @@ -233,6 +235,7 @@ static void init() { } } + @SuppressWarnings("deprecation") private static void register(Block block) { if (block.id >= 0 && block.id < IDENTIFIERS.length) { String identifier = IDENTIFIERS[block.id]; diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockIdFixer.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockIdFixer.java new file mode 100644 index 000000000..97be5ac91 --- /dev/null +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockIdFixer.java @@ -0,0 +1,19 @@ +package net.ornithemc.osl.blocks.impl.block; + +import net.minecraft.block.Block; + +import net.ornithemc.osl.registries.api.registry.sync.IdFixer; + +public class BlockIdFixer implements IdFixer { + + @Override + public void apply() { + for (int id = 0; id < Block.BY_ID.length; id++) { + Block block = Block.BY_ID[id]; + + if (block != null) { + block.id = id; + } + } + } +} diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockItemsMapper.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockItemsMapper.java new file mode 100644 index 000000000..b1fed95be --- /dev/null +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockItemsMapper.java @@ -0,0 +1,72 @@ +package net.ornithemc.osl.blocks.impl.block; + +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Set; + +import it.unimi.dsi.fastutil.ints.Int2IntFunction; + +import net.minecraft.item.BlockItem; +import net.minecraft.item.Item; + +import net.ornithemc.osl.blocks.impl.mixin.common.BlockItemAccess; +import net.ornithemc.osl.registries.api.registry.sync.IdMapper; +import net.ornithemc.osl.registries.api.registry.sync.RegistryMappings; + +public class BlockItemsMapper implements IdMapper { + + public static BlockItemsMapper of(Item[] items) { + return new BlockItemsMapper(items); + } + + private final Item[] items; + private final Set missing; + + private boolean applied; + + private BlockItemsMapper(Item[] items) { + this.items = items; + this.missing = Collections.newSetFromMap(new IdentityHashMap<>()); + } + + @Override + public void apply(RegistryMappings mappings) { + this.missing.clear(); + this.fixBlockItems(mappings::remap, true); + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + this.fixBlockItems(mappings::unmap, false); + this.missing.clear(); + } + + this.applied = false; + } + + private void fixBlockItems(Int2IntFunction mapper, boolean storeMissing) { + for (Item item : this.items) { + if (item == null || !(item instanceof BlockItem)) { + continue; + } + + BlockItemAccess blockItem = (BlockItemAccess) item; + + if (this.missing.contains(item)) { + continue; + } + + int oldId = blockItem.accessBlock(); + int newId = mapper.applyAsInt(oldId); + + if (newId >= 0) { + blockItem.setBlock(newId); + } else if (storeMissing) { + this.missing.add(item); + } + } + } +} diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockPostInit.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockPostInit.java new file mode 100644 index 000000000..1c4cdcef4 --- /dev/null +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/block/BlockPostInit.java @@ -0,0 +1,7 @@ +package net.ornithemc.osl.blocks.impl.block; + +public interface BlockPostInit { + + void osl$blocks$postInit(); + +} diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockItemAccess.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockItemAccess.java new file mode 100644 index 000000000..3d2ab0c1a --- /dev/null +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockItemAccess.java @@ -0,0 +1,17 @@ +package net.ornithemc.osl.blocks.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.item.BlockItem; + +@Mixin(BlockItem.class) +public interface BlockItemAccess { + + @Accessor("block") + int accessBlock(); + + @Accessor("block") + void setBlock(int block); + +} diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java index 22634ed5c..00bbf4b18 100644 --- a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin.java @@ -2,21 +2,46 @@ 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.Slice; +import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.llamalad7.mixinextras.sugar.Share; -import com.llamalad7.mixinextras.sugar.ref.LocalBooleanRef; - import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.entity.living.mob.monster.EndermanEntity; +import net.ornithemc.osl.blocks.api.block.BlockExtension; import net.ornithemc.osl.blocks.impl.BlockRegistryImpl; +import net.ornithemc.osl.blocks.impl.VanillaBlocks; +import net.ornithemc.osl.blocks.impl.block.BlockPostInit; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.core.impl.util.MinecraftVersion; +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.api.registry.SyncedRegistries; +import net.ornithemc.osl.registries.api.registry.sync.BooleanArrayMapper; +import net.ornithemc.osl.registries.api.registry.sync.DynamicArrays; +import net.ornithemc.osl.registries.api.registry.sync.IntArrayMapper; +import net.ornithemc.osl.registries.api.registry.sync.ObjectArrayMapper; @Mixin(Block.class) -public class BlockMixin { +public abstract class BlockMixin implements BlockExtension { + + @Shadow @Final @Mutable + private static Block[] BY_ID; + @Shadow @Final @Mutable + private static boolean[] IS_SOLID_RENDER; + @Shadow @Final @Mutable + private static int[] OPACITIES; + @Shadow @Final @Mutable + private static boolean[] IS_TRANSLUCENT; + @Shadow @Final @Mutable + private static int[] LIGHT; @Inject( method = "", @@ -30,31 +55,98 @@ public class BlockMixin { @Inject( method = "", - slice = @Slice( - from = @At( - value = "FIELD", - opcode = Opcodes.PUTSTATIC, - target = "Lnet/minecraft/block/Block;STONE:Lnet/minecraft/block/Block;" - ) - ), at = @At( - value = "CONSTANT", - args = "intValue=256", - ordinal = 0 + // inject before the for-loop for checking USES_NEIGHBOR_LIGHT + value = "JUMP", + opcode = Opcodes.IF_ICMPGE, + shift = Shift.BY, + // it's extreme but this ensures that the injector is only invoked once + by = -5 + ) + ) + private static void osl$blocks$registerBlocks(CallbackInfo ci) { + // in Beta 1.2 and above Item class init will happen before this point + // but that should not matter as there is a separate event for block + // item registration + BlockRegistryImpl.registerBlocks(); + } + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private static void osl$blocks$registerArrayMappers(CallbackInfo ci) { + BlockRegistryImpl.registerUnknownBlocks(); + + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block/by_id"), ObjectArrayMapper.of(BY_ID)); + if (MinecraftVersion.resolve().compareTo("b1.5_02") <= 0) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block/is_solid"), BooleanArrayMapper.of(IS_SOLID_RENDER)); + } else { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block/is_solid_render"), BooleanArrayMapper.of(IS_SOLID_RENDER)); + } + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block/opacity"), IntArrayMapper.of(OPACITIES)); + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block/is_translucent"), BooleanArrayMapper.of(IS_TRANSLUCENT)); + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block/light"), IntArrayMapper.of(LIGHT)); + + if (MinecraftVersion.resolve().compareTo("b1.8") >= 0) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block/enderman_holdable"), BooleanArrayMapper.of(EndermanEntity.HOLDABLE_BLOCKS)); + } + + for (Block block : BY_ID) { + if (block instanceof BlockPostInit) { + ((BlockPostInit) block).osl$blocks$postInit(); + } + } + } + + @ModifyVariable( + method = "", + argsOnly = true, + ordinal = 0, + at = @At( + value = "INVOKE", + target = "Ljava/lang/Object;()V", + shift = Shift.AFTER ) ) - private static void osl$blocks$initAndLockBlockRegistry(CallbackInfo ci, @Share("osl$blocks$blocksRegistered") LocalBooleanRef blocksRegistered) { - // in some versions this injector targets a for-loop - if (!blocksRegistered.get()) { - BlockRegistryImpl.init(); - BlockRegistryImpl.lock(); + private int osl$blocks$handleAutoAssignId(int id) { + if (id == AUTO_ASSIGN_ID) { + // the Block[] array must contain all blocks so this should + // give us a valid ID for the Block registry to use. + id = DynamicArrays.length(BY_ID); + + // keep 0-255 free for all Vanilla blocks + if (id <= VanillaBlocks.MAX_ID) { + id = VanillaBlocks.MAX_ID + 1; + } } - blocksRegistered.set(true); + return id; + } + + @Inject( + method = "", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;", + opcode = Opcodes.GETSTATIC, + args = "array=set" + ) + ) + private void osl$blocks$growArrays(int id, Material material, CallbackInfo ci) { + int capacity = id + 1; + + BY_ID = DynamicArrays.grow(BY_ID, capacity); + IS_SOLID_RENDER = DynamicArrays.grow(IS_SOLID_RENDER, capacity); + OPACITIES = DynamicArrays.grow(OPACITIES, capacity); + IS_TRANSLUCENT = DynamicArrays.grow(IS_TRANSLUCENT, capacity); + LIGHT = DynamicArrays.grow(LIGHT, capacity); } @Override public String toString() { - return "Block{" + BlockRegistryImpl.getKey((Block) (Object) this) + "}"; + return "Block{" + BlockRegistryImpl.getIdentifier((Block) (Object) this) + "}"; } } diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_12w06a.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_12w06a.java new file mode 100644 index 000000000..b37ab0097 --- /dev/null +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_12w06a.java @@ -0,0 +1,53 @@ +package net.ornithemc.osl.blocks.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.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; + +import net.ornithemc.osl.blocks.api.block.BlockExtension; +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.BooleanArrayMapper; +import net.ornithemc.osl.registries.api.registry.sync.DynamicArrays; + +@Mixin(Block.class) +public abstract class BlockMixin_12w06a implements BlockExtension { + + @Shadow @Final @Mutable + private static boolean[] f_08006312; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private static void osl$blocks$registerArrayMappers(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block/ticks_randomly"), BooleanArrayMapper.of(f_08006312)); + } + + @Inject( + method = "", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;", + opcode = Opcodes.GETSTATIC, + args = "array=set" + ) + ) + private void osl$blocks$growArrays(int id, Material material, CallbackInfo ci) { + int capacity = id + 1; + + f_08006312 = DynamicArrays.grow(f_08006312, capacity); + } +} diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_12w40a.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_12w40a.java new file mode 100644 index 000000000..41c383adf --- /dev/null +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_12w40a.java @@ -0,0 +1,53 @@ +package net.ornithemc.osl.blocks.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.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; + +import net.ornithemc.osl.blocks.api.block.BlockExtension; +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.BooleanArrayMapper; +import net.ornithemc.osl.registries.api.registry.sync.DynamicArrays; + +@Mixin(Block.class) +public abstract class BlockMixin_12w40a implements BlockExtension { + + @Shadow @Final @Mutable + private static boolean[] USES_NEIGHBOR_LIGHT; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private static void osl$blocks$registerArrayMappers(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block/uses_neighbor_light"), BooleanArrayMapper.of(USES_NEIGHBOR_LIGHT)); + } + + @Inject( + method = "", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;", + opcode = Opcodes.GETSTATIC, + args = "array=set" + ) + ) + private void osl$blocks$growArrays(int id, Material material, CallbackInfo ci) { + int capacity = id + 1; + + USES_NEIGHBOR_LIGHT = DynamicArrays.grow(USES_NEIGHBOR_LIGHT, capacity); + } +} diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_13w02a.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_13w02a.java new file mode 100644 index 000000000..a2ddb5be2 --- /dev/null +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_13w02a.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.blocks.impl.mixin.common; + +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.CallbackInfoReturnable; + +import net.minecraft.block.Block; + +import net.ornithemc.osl.blocks.api.BlockRegistry; +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.impl.util.Util; + +@Mixin(Block.class) +public class BlockMixin_13w02a { + + @Shadow + private String key; + + @Inject( + method = "getTranslationKey", + at = @At( + value = "HEAD" + ) + ) + private void osl$blocks$autoAssignTranslationKey(CallbackInfoReturnable cir) { + if (this.key == null) { + NamespacedIdentifier identifier = BlockRegistry.getIdentifier((Block) (Object) this); + + if (identifier == null) { + this.key = "unknown"; + } else { + this.key = Util.makeTranslationKey(identifier); + } + } + } +} diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_1_3_1_13w01a.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_1_3_1_13w01a.java new file mode 100644 index 000000000..4018f3d1e --- /dev/null +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_1_3_1_13w01a.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.blocks.impl.mixin.common; + +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.CallbackInfoReturnable; + +import net.minecraft.block.Block; + +import net.ornithemc.osl.blocks.api.BlockRegistry; +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.impl.util.Util; + +@Mixin(Block.class) +public class BlockMixin_1_3_1_13w01a { + + @Shadow + private String key; + + @Inject( + method = "getTranslationKey", + at = @At( + value = "HEAD" + ) + ) + private void osl$blocks$autoAssignTranslationKey(CallbackInfoReturnable cir) { + if (this.key == null) { + NamespacedIdentifier identifier = BlockRegistry.getIdentifier((Block) (Object) this); + + if (identifier == null) { + this.key = "tile.unknown"; + } else { + this.key = Util.makeTranslationKey("tile", identifier); + } + } + } +} diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_a1_1_0_12w06a.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_a1_1_0_12w06a.java new file mode 100644 index 000000000..fc19a2cba --- /dev/null +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_a1_1_0_12w06a.java @@ -0,0 +1,53 @@ +package net.ornithemc.osl.blocks.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.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; + +import net.ornithemc.osl.blocks.api.block.BlockExtension; +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.BooleanArrayMapper; +import net.ornithemc.osl.registries.api.registry.sync.DynamicArrays; + +@Mixin(Block.class) +public abstract class BlockMixin_a1_1_0_12w06a implements BlockExtension { + + @Shadow @Final @Mutable + private static boolean[] f_72646756; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private static void osl$blocks$registerArrayMappers(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block/has_block_entity"), BooleanArrayMapper.of(f_72646756)); + } + + @Inject( + method = "", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;", + opcode = Opcodes.GETSTATIC, + args = "array=set" + ) + ) + private void osl$blocks$growArrays(int id, Material material, CallbackInfo ci) { + int capacity = id + 1; + + f_72646756 = DynamicArrays.grow(f_72646756, capacity); + } +} diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_b1_0_1_3.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_b1_0_1_3.java new file mode 100644 index 000000000..59380b977 --- /dev/null +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_b1_0_1_3.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.blocks.impl.mixin.common; + +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.CallbackInfoReturnable; + +import net.minecraft.block.Block; + +import net.ornithemc.osl.blocks.api.BlockRegistry; +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.impl.util.Util; + +@Mixin(Block.class) +public class BlockMixin_b1_0_1_3 { + + @Shadow + private String key; + + @Inject( + method = "m_27822537", + at = @At( + value = "HEAD" + ) + ) + private void osl$blocks$autoAssignTranslationKey(CallbackInfoReturnable cir) { + if (this.key == null) { + NamespacedIdentifier identifier = BlockRegistry.getIdentifier((Block) (Object) this); + + if (identifier == null) { + this.key = "tile.unknown"; + } else { + this.key = Util.makeTranslationKey("tile", identifier); + } + } + } +} diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_b1_6_tb3_1_4_7.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_b1_6_tb3_1_4_7.java new file mode 100644 index 000000000..222607a8f --- /dev/null +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_b1_6_tb3_1_4_7.java @@ -0,0 +1,53 @@ +package net.ornithemc.osl.blocks.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.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; + +import net.ornithemc.osl.blocks.api.block.BlockExtension; +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.BooleanArrayMapper; +import net.ornithemc.osl.registries.api.registry.sync.DynamicArrays; + +@Mixin(Block.class) +public abstract class BlockMixin_b1_6_tb3_1_4_7 implements BlockExtension { + + @Shadow @Final @Mutable + private static boolean[] f_47406756; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private static void osl$blocks$registerArrayMappers(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block/update_clients"), BooleanArrayMapper.of(f_47406756)); + } + + @Inject( + method = "", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;", + opcode = Opcodes.GETSTATIC, + args = "array=set" + ) + ) + private void osl$blocks$growArrays(int id, Material material, CallbackInfo ci) { + int capacity = id + 1; + + f_47406756 = DynamicArrays.grow(f_47406756, capacity); + } +} diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_b1_9_pre5_12w38b.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_b1_9_pre5_12w38b.java new file mode 100644 index 000000000..d9de538d2 --- /dev/null +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/BlockMixin_b1_9_pre5_12w38b.java @@ -0,0 +1,53 @@ +package net.ornithemc.osl.blocks.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.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; + +import net.ornithemc.osl.blocks.api.block.BlockExtension; +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.BooleanArrayMapper; +import net.ornithemc.osl.registries.api.registry.sync.DynamicArrays; + +@Mixin(Block.class) +public abstract class BlockMixin_b1_9_pre5_12w38b implements BlockExtension { + + @Shadow @Final @Mutable + private static boolean[] f_81217054; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private static void osl$blocks$registerArrayMappers(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block/uses_neighbor_light"), BooleanArrayMapper.of(f_81217054)); + } + + @Inject( + method = "", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;", + opcode = Opcodes.GETSTATIC, + args = "array=set" + ) + ) + private void osl$blocks$growArrays(int id, Material material, CallbackInfo ci) { + int capacity = id + 1; + + f_81217054 = DynamicArrays.grow(f_81217054, capacity); + } +} diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/EndermanEntityMixin.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/EndermanEntityMixin.java new file mode 100644 index 000000000..1b8db7f6c --- /dev/null +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/EndermanEntityMixin.java @@ -0,0 +1,37 @@ +package net.ornithemc.osl.blocks.impl.mixin.common; + +import org.objectweb.asm.Opcodes; + +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.At.Shift; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.block.Block; +import net.minecraft.entity.living.mob.monster.EndermanEntity; + +import net.ornithemc.osl.registries.api.registry.sync.DynamicArrays; + +@Mixin(EndermanEntity.class) +public class EndermanEntityMixin { + + @Shadow + private static boolean[] HOLDABLE_BLOCKS; + + @Inject( + method = "", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/entity/living/mob/monster/EndermanEntity;HOLDABLE_BLOCKS:[Z", + opcode = Opcodes.PUTSTATIC, + shift = Shift.AFTER + ) + ) + private static void osl$blocks$growArray(CallbackInfo ci) { + int capacity = Block.BY_ID.length; + + HOLDABLE_BLOCKS = DynamicArrays.grow(HOLDABLE_BLOCKS, capacity); + } +} diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/FireBlockMixin.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/FireBlockMixin.java new file mode 100644 index 000000000..5ef90b243 --- /dev/null +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/FireBlockMixin.java @@ -0,0 +1,53 @@ +package net.ornithemc.osl.blocks.impl.mixin.common; + +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.block.FireBlock; + +import net.ornithemc.osl.blocks.api.BlockRegistry; +import net.ornithemc.osl.blocks.impl.block.BlockPostInit; +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.api.registry.SyncedRegistries; +import net.ornithemc.osl.registries.api.registry.sync.DynamicArrays; +import net.ornithemc.osl.registries.api.registry.sync.IntArrayMapper; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +@Mixin(FireBlock.class) +public class FireBlockMixin implements BlockPostInit { + + @Shadow + private int[] flammability; + @Shadow + private int[] burnChance; + + @Inject( + method = "setFlammable", + at = @At( + value = "HEAD" + ) + ) + private void osl$blocks$growArrays(int block, int flammability, int burnChance, CallbackInfo ci) { + int capacity = block + 1; + + this.flammability = DynamicArrays.grow(this.flammability, capacity); + this.burnChance = DynamicArrays.grow(this.burnChance, capacity); + } + + @Override + public void osl$blocks$postInit() { + FireBlock block = (FireBlock) (Object) this; + NamespacedIdentifier identifier = BlockRegistry.getIdentifier(block); + + if (identifier == null) { + RegistriesImpl.LOGGER.warn("Unable to register FireBlock array mappers for unregistered block {} (ID {})", block, block.id); + } else { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, identifier.suffixed("/flammability"), IntArrayMapper.of(this.flammability)); + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, identifier.suffixed("/burn_chance"), IntArrayMapper.of(this.burnChance)); + } + } +} diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/ItemMixin.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/ItemMixin.java new file mode 100644 index 000000000..503e7eb0a --- /dev/null +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/ItemMixin.java @@ -0,0 +1,31 @@ +package net.ornithemc.osl.blocks.impl.mixin.common; + +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.item.Item; + +import net.ornithemc.osl.blocks.impl.block.BlockItemsMapper; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.api.registry.SyncedRegistries; + +@Mixin(Item.class) +public class ItemMixin { + + @Shadow + private static Item[] BY_ID; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private static void osl$items$registerBlockItemMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block/item"), BlockItemsMapper.of(BY_ID)); + } +} diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/StatsMixin.java b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/StatsMixin.java new file mode 100644 index 000000000..6b714741c --- /dev/null +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/blocks/impl/mixin/common/StatsMixin.java @@ -0,0 +1,34 @@ +package net.ornithemc.osl.blocks.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.stat.Stat; +import net.minecraft.stat.Stats; + +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.ObjectArrayMapper; + +@Mixin(Stats.class) +public class StatsMixin { + + @Shadow @Final + private static Stat[] BLOCKS_MINED; + + @Inject( + method = "initItemsCraftedStats", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/stat/Stats;mergeBlockStats([Lnet/minecraft/stat/Stat;)V" + ) + ) + private static void osl$items$registerStatsMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("stats/mined"), ObjectArrayMapper.of(BLOCKS_MINED)); + } +} diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/resources/fabric.mod.json b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/resources/fabric.mod.json index 044ed4365..89ea1d34e 100644 --- a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/resources/fabric.mod.json +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/resources/fabric.mod.json @@ -3,6 +3,11 @@ "id": "osl-blocks", "version": "0.1.1+mca1.0.1_01-mc1.6.4", "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.blocks.impl.BlockRegistryImpl::init" + ] + }, "mixins": [ "osl.blocks.mixins.json" ], @@ -10,7 +15,14 @@ "depends": { "fabricloader": "\u003e\u003d0.18.0", "minecraft": "\u003e\u003d1.0.0-alpha.0.1 \u003c\u003d1.6.4", - "osl-core": "\u003e\u003d0.9.0" + "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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0", + "osl-registries": "\u003e\u003d0.1.0-" }, "name": "OSL Blocks", "description": "Blocks API and events.", diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/resources/osl.blocks.classtweaker b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/resources/osl.blocks.classtweaker index d4ae7c59e..499656278 100644 --- a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/resources/osl.blocks.classtweaker +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/resources/osl.blocks.classtweaker @@ -11,4 +11,7 @@ transitive-accessible method net/minecraft/block/Block setKey (Ljava/lang/String transitive-accessible method net/minecraft/block/Block setCreativeModeTab (Lnet/minecraft/item/CreativeModeTab;)Lnet/minecraft/block/Block; transitive-accessible method net/minecraft/block/Block setSpriteName (Ljava/lang/String;)Lnet/minecraft/block/Block; -transitive-inject-interface net/minecraft/block/Block net/ornithemc/osl/blocks/impl/block/BlockExtensionImpl \ No newline at end of file +transitive-inject-interface net/minecraft/block/Block net/ornithemc/osl/blocks/impl/block/BlockExtensionImpl + +mutable field net/minecraft/block/Block id I +accessible field net/minecraft/entity/living/mob/monster/EndermanEntity HOLDABLE_BLOCKS [Z diff --git a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/resources/osl.blocks.mixins.json b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/resources/osl.blocks.mixins.json index 3ce092309..3167f0600 100644 --- a/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/resources/osl.blocks.mixins.json +++ b/libraries/blocks/blocks-mca1.0.1_01-mc1.6.4/src/main/resources/osl.blocks.mixins.json @@ -5,11 +5,24 @@ "compatibilityLevel": "JAVA_8", "plugin": "net.ornithemc.osl.blocks.impl.BlocksMixinPlugin", "mixins": [ + "common.BlockItemAccess", + "common.BlockMixin_1_3_1_13w01a", + "common.BlockMixin_12w06a", + "common.BlockMixin_12w40a", + "common.BlockMixin_13w02a", + "common.BlockMixin_a1_1_0_12w06a", + "common.BlockMixin_b1_0_1_3", + "common.BlockMixin_b1_6_tb3_1_4_7", + "common.BlockMixin_b1_9_pre5_12w38b", "common.BlockMixin", "common.BlockMixinNew", "common.BlockMixinOld", + "common.EndermanEntityMixin", + "common.FireBlockMixin", + "common.ItemMixin", "common.RedstoneTorchBlockMixin", "common.RepeaterBlockMixin", + "common.StatsMixin", "common.WorldMixin" ], "client": [ diff --git a/libraries/blocks/gradle.properties b/libraries/blocks/gradle.properties index 32d5d351a..c4c63d1b7 100644 --- a/libraries/blocks/gradle.properties +++ b/libraries/blocks/gradle.properties @@ -3,4 +3,5 @@ library_name = Blocks library_description = Blocks API and events. library_version = 0.1.1 -osl_dependencies = core:>=0.9.0 +entrypoint_init = net.ornithemc.osl.blocks.impl.BlockRegistryImpl::init +osl_dependencies = core:>=0.9.0,entrypoints:>=0.5.0,lifecycle-events:>=0.6.0,executors:>=0.1.0,text-components:>=0.1.0-,networking:>=0.9.0,networking-impl:>=0.1.0,registries:>=0.1.0- diff --git a/libraries/core/core-mc14w27a-mc1.14.4/src/main/java/net/ornithemc/osl/core/impl/mixin/common/IdentifierMixin.java b/libraries/core/core-mc14w27a-mc1.14.4/src/main/java/net/ornithemc/osl/core/impl/mixin/common/IdentifierMixin.java index 86722f15c..d06981302 100644 --- a/libraries/core/core-mc14w27a-mc1.14.4/src/main/java/net/ornithemc/osl/core/impl/mixin/common/IdentifierMixin.java +++ b/libraries/core/core-mc14w27a-mc1.14.4/src/main/java/net/ornithemc/osl/core/impl/mixin/common/IdentifierMixin.java @@ -42,4 +42,14 @@ public String namespace() { public String identifier() { return path; } + + @Override + public NamespacedIdentifier prefixed(String prefix) { + return new Identifier(namespace, prefix + path); + } + + @Override + public NamespacedIdentifier suffixed(String suffix) { + return new Identifier(namespace, path + suffix); + } } diff --git a/libraries/core/core-mca1.0.1_01-mc14w26c/src/main/java/net/ornithemc/osl/core/impl/mixin/client/IdentifierMixin.java b/libraries/core/core-mca1.0.1_01-mc14w26c/src/main/java/net/ornithemc/osl/core/impl/mixin/client/IdentifierMixin.java index 142dd63d7..eb965addf 100644 --- a/libraries/core/core-mca1.0.1_01-mc14w26c/src/main/java/net/ornithemc/osl/core/impl/mixin/client/IdentifierMixin.java +++ b/libraries/core/core-mca1.0.1_01-mc14w26c/src/main/java/net/ornithemc/osl/core/impl/mixin/client/IdentifierMixin.java @@ -42,4 +42,14 @@ public String namespace() { public String identifier() { return path; } + + @Override + public NamespacedIdentifier prefixed(String prefix) { + return new Identifier(namespace, prefix + path); + } + + @Override + public NamespacedIdentifier suffixed(String suffix) { + return new Identifier(namespace, path + suffix); + } } diff --git a/libraries/core/src/main/java/net/ornithemc/osl/core/api/registry/DefaultedIdRegistry.java b/libraries/core/src/main/java/net/ornithemc/osl/core/api/registry/DefaultedIdRegistry.java index 0fb572422..8fb0f1f06 100644 --- a/libraries/core/src/main/java/net/ornithemc/osl/core/api/registry/DefaultedIdRegistry.java +++ b/libraries/core/src/main/java/net/ornithemc/osl/core/api/registry/DefaultedIdRegistry.java @@ -3,6 +3,10 @@ import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +/** + * @deprecated use Registries API instead + */ +@Deprecated public class DefaultedIdRegistry extends SimpleIdRegistry { private final NamespacedIdentifier defaultKey; diff --git a/libraries/core/src/main/java/net/ornithemc/osl/core/api/registry/IdBiMap.java b/libraries/core/src/main/java/net/ornithemc/osl/core/api/registry/IdBiMap.java index 12512e89c..2bdfae846 100644 --- a/libraries/core/src/main/java/net/ornithemc/osl/core/api/registry/IdBiMap.java +++ b/libraries/core/src/main/java/net/ornithemc/osl/core/api/registry/IdBiMap.java @@ -7,6 +7,10 @@ import it.unimi.dsi.fastutil.objects.Reference2IntMap; import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; +/** + * @deprecated use Registries API instead + */ +@Deprecated public class IdBiMap implements Iterable { private final Int2ReferenceMap values; diff --git a/libraries/core/src/main/java/net/ornithemc/osl/core/api/registry/SimpleIdRegistry.java b/libraries/core/src/main/java/net/ornithemc/osl/core/api/registry/SimpleIdRegistry.java index 4c9d21735..edfee7844 100644 --- a/libraries/core/src/main/java/net/ornithemc/osl/core/api/registry/SimpleIdRegistry.java +++ b/libraries/core/src/main/java/net/ornithemc/osl/core/api/registry/SimpleIdRegistry.java @@ -13,6 +13,10 @@ import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +/** + * @deprecated use Registries API instead + */ +@Deprecated public class SimpleIdRegistry implements Iterable { private final Int2ReferenceMap values; diff --git a/libraries/core/src/main/java/net/ornithemc/osl/core/api/util/NamespacedIdentifier.java b/libraries/core/src/main/java/net/ornithemc/osl/core/api/util/NamespacedIdentifier.java index 598ac9943..f5435f853 100644 --- a/libraries/core/src/main/java/net/ornithemc/osl/core/api/util/NamespacedIdentifier.java +++ b/libraries/core/src/main/java/net/ornithemc/osl/core/api/util/NamespacedIdentifier.java @@ -35,4 +35,14 @@ public interface NamespacedIdentifier { */ String identifier(); + /** + * @return a copy of this {@code NamespacedIdentifier} with the given prefix. + */ + NamespacedIdentifier prefixed(String prefix); + + /** + * @return a copy of this {@code NamespacedIdentifier} with the given suffix. + */ + NamespacedIdentifier suffixed(String suffix); + } diff --git a/libraries/core/src/main/java/net/ornithemc/osl/core/impl/util/IdentifierImpl.java b/libraries/core/src/main/java/net/ornithemc/osl/core/impl/util/IdentifierImpl.java index 0358d11b6..ce9caea96 100644 --- a/libraries/core/src/main/java/net/ornithemc/osl/core/impl/util/IdentifierImpl.java +++ b/libraries/core/src/main/java/net/ornithemc/osl/core/impl/util/IdentifierImpl.java @@ -15,4 +15,14 @@ default String namespace() { default String identifier() { throw new AbstractMethodError("Not implemented!"); } + + @Override + default NamespacedIdentifier prefixed(String prefix) { + throw new AbstractMethodError("Not implemented!"); + } + + @Override + default NamespacedIdentifier suffixed(String prefix) { + throw new AbstractMethodError("Not implemented!"); + } } diff --git a/libraries/core/src/main/java/net/ornithemc/osl/core/impl/util/NamespacedIdentifierImpl.java b/libraries/core/src/main/java/net/ornithemc/osl/core/impl/util/NamespacedIdentifierImpl.java index f373c4363..9080f4152 100644 --- a/libraries/core/src/main/java/net/ornithemc/osl/core/impl/util/NamespacedIdentifierImpl.java +++ b/libraries/core/src/main/java/net/ornithemc/osl/core/impl/util/NamespacedIdentifierImpl.java @@ -54,4 +54,14 @@ public String namespace() { public String identifier() { return identifier; } + + @Override + public NamespacedIdentifier prefixed(String prefix) { + return new NamespacedIdentifierImpl(namespace, prefix + identifier); + } + + @Override + public NamespacedIdentifier suffixed(String suffix) { + return new NamespacedIdentifierImpl(namespace, identifier + suffix); + } } diff --git a/libraries/core/src/main/java/net/ornithemc/osl/core/impl/util/Util.java b/libraries/core/src/main/java/net/ornithemc/osl/core/impl/util/Util.java index 68b106277..deff3908e 100644 --- a/libraries/core/src/main/java/net/ornithemc/osl/core/impl/util/Util.java +++ b/libraries/core/src/main/java/net/ornithemc/osl/core/impl/util/Util.java @@ -4,8 +4,22 @@ import java.util.List; import java.util.concurrent.CompletableFuture; +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; + public final class Util { + public static String makeTranslationKey(NamespacedIdentifier identifier) { + return identifier.namespace() + "." + identifier.identifier().replace('/', '.'); + } + + public static String makeTranslationKey(String prefix, NamespacedIdentifier identifier) { + return prefix + "." + makeTranslationKey(identifier); + } + + public static String makeTranslationKey(String prefix, NamespacedIdentifier identifier, String suffix) { + return makeTranslationKey(prefix, identifier) + "." + suffix; + } + public static CompletableFuture> sequence(List> futures) { List results = new ArrayList<>(futures.size()); diff --git a/libraries/items/gradle.properties b/libraries/items/gradle.properties index b5cf61cbe..994fbee8d 100644 --- a/libraries/items/gradle.properties +++ b/libraries/items/gradle.properties @@ -3,4 +3,5 @@ library_name = Items library_description = Items API and events. library_version = 0.1.0 -osl_dependencies = core:>=0.9.0,blocks:>=0.1.0 +entrypoint_init = net.ornithemc.osl.items.impl.ItemRegistryImpl::init +osl_dependencies = core:>=0.9.0,entrypoints:>=0.5.0,lifecycle-events:>=0.6.0,executors:>=0.1.0,text-components:>=0.1.0-,networking:>=0.9.0,networking-impl:>=0.1.0,registries:>=0.1.0-,blocks:>=0.1.0 diff --git a/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/api/ItemEvents.java b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/api/ItemEvents.java index 4d0923b99..e4b60f8b4 100644 --- a/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/api/ItemEvents.java +++ b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/api/ItemEvents.java @@ -22,7 +22,7 @@ public final class ItemEvents { *
 	 * {@code
 	 * ItemEvents.REGISTER_ITEMS.register(() -> {
-	 * 	ItemRegistry.register(999, NamespacedIdentifiers.from("example", "cookie"), new CookieItem());
+	 * 	ItemRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new CookieItem());
 	 * });
 	 * }
 	 * 
diff --git a/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java index 5c9fdcbc3..c7b4f4573 100644 --- a/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java +++ b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java @@ -8,12 +8,16 @@ import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.items.impl.ItemRegistryImpl; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; /** * Public access to the Items registry. */ public final class ItemRegistry { + public static final Registry REGISTRY = ItemRegistryImpl.REGISTRY; + /** * @return the numerical ID assigned to the given item. */ @@ -24,7 +28,14 @@ public static int getId(Item item) { /** * @return the namespaced ID assigned to the given item. */ - public static NamespacedIdentifier getKey(Item item) { + public static NamespacedIdentifier getIdentifier(Item item) { + return ItemRegistryImpl.getIdentifier(item); + } + + /** + * @return the resource key assigned to the given item. + */ + public static ResourceKey getKey(Item item) { return ItemRegistryImpl.getKey(item); } @@ -38,14 +49,35 @@ public static Item getItem(int id) { /** * @return the item mapped to the given namespaced ID. */ - public static Item getItem(NamespacedIdentifier key) { + public static Item getItem(NamespacedIdentifier identifier) { + return ItemRegistryImpl.getItem(identifier); + } + + /** + * @return the item mapped to the given resource key. + */ + public static Item getItem(ResourceKey key) { return ItemRegistryImpl.getItem(key); } + /** + * @return the item mapped to the given block. + */ + public static Item getItem(Block block) { + return ItemRegistryImpl.getItem(block); + } + /** * @return a set containing all namespaced IDs in the registry. */ - public static Set keySet() { + public static Set identifierSet() { + return ItemRegistryImpl.identifierSet(); + } + + /** + * @return a set containing all resource keys in the registry. + */ + public static Set> keySet() { return ItemRegistryImpl.keySet(); } @@ -76,13 +108,37 @@ public static T register(Block block, T item) { return ItemRegistryImpl.register(block, item); } + /** + * @param the item type. + * @param identifier the namespaced ID of the item. + * @param item the item to register. + * @return the registered item. + */ + public static T register(NamespacedIdentifier identifier, T item) { + return ItemRegistryImpl.register(identifier, item); + } + + /** + * @param the item type. + * @param key the resource key of the item. + * @param item the item to register. + * @return the registered item. + */ + public static T register(ResourceKey key, T item) { + return ItemRegistryImpl.register(key, item); + } + /** * @param the item type. * @param id the numerical ID of the item. * @param key the namespaced ID of the item. * @param item the item to register. * @return the registered item. + * + * @deprecated use {@linkplain #register(NamespacedIdentifier, Item)} + * or {@linkplain #register(ResourceKey, Item)} instead. */ + @Deprecated public static T register(int id, NamespacedIdentifier key, T item) { return ItemRegistryImpl.register(id, key, item); } diff --git a/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java index 72e7dace4..ba2a299ed 100644 --- a/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java +++ b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java @@ -3,7 +3,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; import net.minecraft.block.Block; import net.minecraft.item.BlockItem; @@ -11,36 +10,55 @@ import net.ornithemc.osl.blocks.api.BlockRegistry; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; -import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; import net.ornithemc.osl.items.api.ItemEvents; import net.ornithemc.osl.items.impl.mixin.common.BlockItemAccess; +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 ItemRegistryImpl { + public static final Registry REGISTRY = VanillaRegistries.registerSimple(RegistryKeys.ITEM, Item.REGISTRY); public static final Map BLOCK_ITEMS = new HashMap<>(); private static boolean locked = true; - private static boolean initialized = false; public static int getId(Item item) { - return Item.REGISTRY.getId(item); + return REGISTRY.getId(item); } - public static NamespacedIdentifier getKey(Item item) { - String key = Item.REGISTRY.getKey(item); - return key == null ? null : NamespacedIdentifiers.parse(key); + public static NamespacedIdentifier getIdentifier(Item item) { + return REGISTRY.getIdentifier(item); + } + + public static ResourceKey getKey(Item item) { + return REGISTRY.getKey(item); } public static Item getItem(int id) { - return Item.REGISTRY.get(id); + return REGISTRY.get(id); + } + + public static Item getItem(NamespacedIdentifier identifier) { + return REGISTRY.get(identifier); + } + + public static Item getItem(ResourceKey key) { + return REGISTRY.get(key); } - public static Item getItem(NamespacedIdentifier key) { - return Item.REGISTRY.get(key.toString()); + public static Item getItem(Block block) { + return Item.byBlock(block); } - public static Set keySet() { - return Item.REGISTRY.keySet().stream().map(NamespacedIdentifiers::parse).collect(Collectors.toSet()); + public static Set identifierSet() { + return REGISTRY.identifierSet(); + } + + public static Set> keySet() { + return REGISTRY.keySet(); } public static BlockItem register(Block block) { @@ -56,41 +74,43 @@ public static T register(Block block, T item) { BLOCK_ITEMS.put(block, item); } - return register(BlockRegistry.getId(block), BlockRegistry.getKey(block), item); + return register(BlockRegistry.getIdentifier(block), item); } - public static T register(int id, NamespacedIdentifier key, T item) { + public static T register(NamespacedIdentifier identifier, T item) { if (locked) { - throw new IllegalStateException("register called too " + (initialized ? "late" : "early") + ": registry locked!"); + throw new IllegalStateException("register called too early: registry locked!"); } else { - Item.REGISTRY.register(id, key.toString(), item); + return Registry.register(REGISTRY, identifier, item); } + } - return item; + public static T register(ResourceKey key, T item) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, key, item); + } } - public static void lock() { - if (!initialized) { - throw new IllegalStateException("cannot lock item registry unless it's been initialized!"); + @Deprecated + public static T register(int id, NamespacedIdentifier key, T item) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, id, key, item); } + } - locked = true; + public static void init() { + SyncedRegistries.register(RegistryKeys.ITEM); } public static void unlock() { - if (initialized) { - throw new IllegalStateException("cannot unlock item registry once it's been initialized!"); - } - locked = false; } - public static void init() { - if (locked) { - throw new IllegalStateException("cannot initialize item registry when it's locked!"); - } - + public static void registerItems() { ItemEvents.REGISTER_ITEMS.invoker().run(); - initialized = true; } } diff --git a/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/ItemsMixinPlugin.java b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/ItemsMixinPlugin.java index 03397a6ae..9c1787358 100644 --- a/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/ItemsMixinPlugin.java +++ b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/ItemsMixinPlugin.java @@ -13,6 +13,7 @@ public class ItemsMixinPlugin implements IMixinConfigPlugin { public static final boolean SPECIAL_BLOCK_ITEM_HANDLING = MinecraftVersion.resolve().compareTo("13w37a") >= 0; + public static final boolean BLOCK_ITEMS_MAP_EXISTS = MinecraftVersion.resolve().compareTo("14w25a") >= 0; @Override public void onLoad(String mixinPackage) { @@ -31,6 +32,12 @@ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { if ("net.ornithemc.osl.items.impl.mixin.common.ItemMixinOld".equals(mixinClassName)) { return !SPECIAL_BLOCK_ITEM_HANDLING; } + if ("net.ornithemc.osl.items.impl.mixin.common.ItemMixin_14w21b".equals(mixinClassName)) { + return !BLOCK_ITEMS_MAP_EXISTS; + } + if ("net.ornithemc.osl.items.impl.mixin.common.ItemMixin_14w25a".equals(mixinClassName)) { + return BLOCK_ITEMS_MAP_EXISTS; + } return true; } diff --git a/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java new file mode 100644 index 000000000..356aaff28 --- /dev/null +++ b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java @@ -0,0 +1,54 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.impl.util.Util; +import net.ornithemc.osl.items.api.ItemRegistry; + +@Mixin(Item.class) +public class ItemMixin { + + @Shadow + private String key; + + @Inject( + method = "getTranslationKey()Ljava/lang/String;", + at = @At( + value = "HEAD" + ) + ) + private void osl$items$autoAssignTranslationKey1(CallbackInfoReturnable cir) { + this.ensureTranslationKeyExists(); + } + + @Inject( + method = "getTranslationKey(Lnet/minecraft/item/ItemStack;)Ljava/lang/String;", + at = @At( + value = "HEAD" + ) + ) + private void osl$items$autoAssignTranslationKey2(CallbackInfoReturnable cir) { + this.ensureTranslationKeyExists(); + } + + @Unique + private void ensureTranslationKeyExists() { + if (this.key == null) { + NamespacedIdentifier identifier = ItemRegistry.getIdentifier((Item) (Object) this); + + if (identifier == null) { + this.key = "unknown"; + } else { + this.key = Util.makeTranslationKey(identifier); + } + } + } +} diff --git a/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixinNew.java b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixinNew.java index 017fd6764..7153867b7 100644 --- a/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixinNew.java +++ b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixinNew.java @@ -34,10 +34,10 @@ public class ItemMixinNew { target = "Lnet/minecraft/util/registry/IdRegistry;keySet()Ljava/util/Set;" ) ) - private static void osl$items$initAndLockItemRegistry(CallbackInfo ci, @Local HashSet blocksToSkip) { - ItemRegistryImpl.init(); - ItemRegistryImpl.lock(); + private static void osl$items$registerItems(CallbackInfo ci, @Local HashSet blocksToSkip) { + ItemRegistryImpl.registerItems(); + // this set contains all blocks for which not to auto-generate block items blocksToSkip.addAll(ItemRegistryImpl.BLOCK_ITEMS.keySet()); } } diff --git a/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixinOld.java b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixinOld.java index b9cc935ab..a7bc4ac05 100644 --- a/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixinOld.java +++ b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixinOld.java @@ -37,9 +37,8 @@ public class ItemMixinOld { target = "Lnet/minecraft/util/registry/IdRegistry;keySet()Ljava/util/Set;" ) ) - private static void osl$items$initAndLockItemRegistry(CallbackInfo ci) { - ItemRegistryImpl.init(); - ItemRegistryImpl.lock(); + private static void osl$items$registerItems(CallbackInfo ci) { + ItemRegistryImpl.registerItems(); } @WrapOperation( diff --git a/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin_14w21b.java b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin_14w21b.java new file mode 100644 index 000000000..eec9d9fa2 --- /dev/null +++ b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin_14w21b.java @@ -0,0 +1,51 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Slice; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.items.api.ItemRegistry; +import net.ornithemc.osl.items.impl.ItemRegistryImpl; + +@Mixin(Item.class) +public class ItemMixin_14w21b { + + @Overwrite + public static Item byBlock(Block block) { + return ItemRegistryImpl.BLOCK_ITEMS.get(block); + } + + @WrapOperation( + method = "init", + slice = @Slice( + from = @At( + value = "INVOKE", + target = "Lnet/minecraft/block/Block;getId(Lnet/minecraft/block/Block;)I" + ) + ), + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/util/registry/IdRegistry;register(ILjava/lang/String;Ljava/lang/Object;)V" + ) + ) + private static void osl$items$registerVanillaBlockItem(IdRegistry registry, int id, String key, Object value, Operation op, @Local Block block) { + op.call(registry, id, key, value); + + Item item = (Item) value; + NamespacedIdentifier identifier = ItemRegistry.getIdentifier(item); + + if (identifier != null) { + ItemRegistryImpl.BLOCK_ITEMS.put(block, item); + } + } +} diff --git a/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin_14w25a.java b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin_14w25a.java new file mode 100644 index 000000000..7230ede76 --- /dev/null +++ b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin_14w25a.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import java.util.Map; + +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.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; + +import net.ornithemc.osl.items.impl.ItemRegistryImpl; + +@Mixin(Item.class) +public class ItemMixin_14w25a { + + @Shadow @Final @Mutable + private static Map f_62044349; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private static void osl$items$replaceBlockItemsMap(CallbackInfo ci) { + f_62044349 = ItemRegistryImpl.BLOCK_ITEMS; + } +} diff --git a/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/StatsMixin.java b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/StatsMixin.java new file mode 100644 index 000000000..13c0a2a18 --- /dev/null +++ b/libraries/items/items-mc13w36a-mc14w25b/src/main/java/net/ornithemc/osl/items/impl/mixin/common/StatsMixin.java @@ -0,0 +1,52 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import java.util.Map; + +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.stat.Stat; +import net.minecraft.stat.Stats; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.core.impl.util.MinecraftVersion; +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.api.registry.SyncedRegistries; +import net.ornithemc.osl.registries.api.registry.sync.ObjectArrayMapper; +import net.ornithemc.osl.registries.impl.registry.sync.StatsMapper; + +@Mixin(Stats.class) +public class StatsMixin { + + @Shadow @Final + private static Map BY_KEY; + @Shadow @Final + private static Stat[] ITEMS_CRAFTED; + @Shadow @Final + private static Stat[] ITEMS_USED; + @Shadow @Final + private static Stat[] ITEMS_BROKEN; + + @Inject( + // inject at init instead of in case the arrays are resized... + method = "init", + at = @At( + value = "TAIL" + ) + ) + private static void osl$items$registerStatsMapper(CallbackInfo ci) { + if (MinecraftVersion.resolve().compareTo("14w06a") < 0) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("stats/crafted"), StatsMapper.of(BY_KEY, ITEMS_CRAFTED)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("stats/used"), StatsMapper.of(BY_KEY, ITEMS_USED)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("stats/broken"), StatsMapper.of(BY_KEY, ITEMS_BROKEN)); + } else { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("stats/crafted"), ObjectArrayMapper.of(ITEMS_CRAFTED)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("stats/used"), ObjectArrayMapper.of(ITEMS_USED)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("stats/broken"), ObjectArrayMapper.of(ITEMS_BROKEN)); + } + } +} diff --git a/libraries/items/items-mc13w36a-mc14w25b/src/main/resources/fabric.mod.json b/libraries/items/items-mc13w36a-mc14w25b/src/main/resources/fabric.mod.json index d1b645c9c..091245c13 100644 --- a/libraries/items/items-mc13w36a-mc14w25b/src/main/resources/fabric.mod.json +++ b/libraries/items/items-mc13w36a-mc14w25b/src/main/resources/fabric.mod.json @@ -3,6 +3,11 @@ "id": "osl-items", "version": "0.1.0+mc13w36a-mc14w25b", "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.items.impl.ItemRegistryImpl::init" + ] + }, "mixins": [ "osl.items.mixins.json" ], @@ -11,6 +16,13 @@ "fabricloader": "\u003e\u003d0.18.0", "minecraft": "\u003e\u003d1.7-alpha.13.36.a \u003c\u003d1.8-alpha.14.25.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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0", + "osl-registries": "\u003e\u003d0.1.0-", "osl-blocks": "\u003e\u003d0.1.0" }, "name": "OSL Items", diff --git a/libraries/items/items-mc13w36a-mc14w25b/src/main/resources/osl.items.mixins.json b/libraries/items/items-mc13w36a-mc14w25b/src/main/resources/osl.items.mixins.json index 23794a0f8..3eacdfb05 100644 --- a/libraries/items/items-mc13w36a-mc14w25b/src/main/resources/osl.items.mixins.json +++ b/libraries/items/items-mc13w36a-mc14w25b/src/main/resources/osl.items.mixins.json @@ -6,8 +6,12 @@ "plugin": "net.ornithemc.osl.items.impl.ItemsMixinPlugin", "mixins": [ "common.BlockItemAccess", + "common.ItemMixin_14w21b", + "common.ItemMixin_14w25a", + "common.ItemMixin", "common.ItemMixinNew", - "common.ItemMixinOld" + "common.ItemMixinOld", + "common.StatsMixin" ], "client": [ ], diff --git a/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/api/ItemEvents.java b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/api/ItemEvents.java index 4d0923b99..e4b60f8b4 100644 --- a/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/api/ItemEvents.java +++ b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/api/ItemEvents.java @@ -22,7 +22,7 @@ public final class ItemEvents { *
 	 * {@code
 	 * ItemEvents.REGISTER_ITEMS.register(() -> {
-	 * 	ItemRegistry.register(999, NamespacedIdentifiers.from("example", "cookie"), new CookieItem());
+	 * 	ItemRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new CookieItem());
 	 * });
 	 * }
 	 * 
diff --git a/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java index 5c9fdcbc3..c7b4f4573 100644 --- a/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java +++ b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java @@ -8,12 +8,16 @@ import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.items.impl.ItemRegistryImpl; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; /** * Public access to the Items registry. */ public final class ItemRegistry { + public static final Registry REGISTRY = ItemRegistryImpl.REGISTRY; + /** * @return the numerical ID assigned to the given item. */ @@ -24,7 +28,14 @@ public static int getId(Item item) { /** * @return the namespaced ID assigned to the given item. */ - public static NamespacedIdentifier getKey(Item item) { + public static NamespacedIdentifier getIdentifier(Item item) { + return ItemRegistryImpl.getIdentifier(item); + } + + /** + * @return the resource key assigned to the given item. + */ + public static ResourceKey getKey(Item item) { return ItemRegistryImpl.getKey(item); } @@ -38,14 +49,35 @@ public static Item getItem(int id) { /** * @return the item mapped to the given namespaced ID. */ - public static Item getItem(NamespacedIdentifier key) { + public static Item getItem(NamespacedIdentifier identifier) { + return ItemRegistryImpl.getItem(identifier); + } + + /** + * @return the item mapped to the given resource key. + */ + public static Item getItem(ResourceKey key) { return ItemRegistryImpl.getItem(key); } + /** + * @return the item mapped to the given block. + */ + public static Item getItem(Block block) { + return ItemRegistryImpl.getItem(block); + } + /** * @return a set containing all namespaced IDs in the registry. */ - public static Set keySet() { + public static Set identifierSet() { + return ItemRegistryImpl.identifierSet(); + } + + /** + * @return a set containing all resource keys in the registry. + */ + public static Set> keySet() { return ItemRegistryImpl.keySet(); } @@ -76,13 +108,37 @@ public static T register(Block block, T item) { return ItemRegistryImpl.register(block, item); } + /** + * @param the item type. + * @param identifier the namespaced ID of the item. + * @param item the item to register. + * @return the registered item. + */ + public static T register(NamespacedIdentifier identifier, T item) { + return ItemRegistryImpl.register(identifier, item); + } + + /** + * @param the item type. + * @param key the resource key of the item. + * @param item the item to register. + * @return the registered item. + */ + public static T register(ResourceKey key, T item) { + return ItemRegistryImpl.register(key, item); + } + /** * @param the item type. * @param id the numerical ID of the item. * @param key the namespaced ID of the item. * @param item the item to register. * @return the registered item. + * + * @deprecated use {@linkplain #register(NamespacedIdentifier, Item)} + * or {@linkplain #register(ResourceKey, Item)} instead. */ + @Deprecated public static T register(int id, NamespacedIdentifier key, T item) { return ItemRegistryImpl.register(id, key, item); } diff --git a/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java index 428f6240d..52189cf4a 100644 --- a/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java +++ b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java @@ -1,40 +1,60 @@ package net.ornithemc.osl.items.impl; -import java.util.Collections; import java.util.Set; import net.minecraft.block.Block; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; -import net.minecraft.resource.Identifier; import net.ornithemc.osl.blocks.api.BlockRegistry; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.items.api.ItemEvents; +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 ItemRegistryImpl { + public static final Registry REGISTRY = VanillaRegistries.registerSimple(RegistryKeys.ITEM, Item.REGISTRY); + private static boolean locked = true; - private static boolean initialized = false; public static int getId(Item item) { - return Item.REGISTRY.getId(item); + return REGISTRY.getId(item); + } + + public static NamespacedIdentifier getIdentifier(Item item) { + return REGISTRY.getIdentifier(item); } - public static NamespacedIdentifier getKey(Item item) { - return Item.REGISTRY.getKey(item); + public static ResourceKey getKey(Item item) { + return REGISTRY.getKey(item); } public static Item getItem(int id) { - return Item.REGISTRY.get(id); + return REGISTRY.get(id); + } + + public static Item getItem(NamespacedIdentifier identifier) { + return REGISTRY.get(identifier); + } + + public static Item getItem(ResourceKey key) { + return REGISTRY.get(key); } - public static Item getItem(NamespacedIdentifier key) { - return Item.REGISTRY.get(identifier(key)); + public static Item getItem(Block block) { + return Item.byBlock(block); } - public static Set keySet() { - return Collections.unmodifiableSet(Item.REGISTRY.keySet()); + public static Set identifierSet() { + return REGISTRY.identifierSet(); + } + + public static Set> keySet() { + return REGISTRY.keySet(); } public static BlockItem register(Block block) { @@ -50,45 +70,43 @@ public static T register(Block block, T item) { Item.BLOCK_ITEMS.put(block, item); } - return register(BlockRegistry.getId(block), BlockRegistry.getKey(block), item); + return register(BlockRegistry.getIdentifier(block), item); } - public static T register(int id, NamespacedIdentifier key, T item) { + public static T register(NamespacedIdentifier identifier, T item) { if (locked) { - throw new IllegalStateException("register called too " + (initialized ? "late" : "early") + ": registry locked!"); + throw new IllegalStateException("register called too early: registry locked!"); } else { - Item.REGISTRY.register(id, identifier(key), item); + return Registry.register(REGISTRY, identifier, item); } - - return item; } - private static Identifier identifier(NamespacedIdentifier id) { - return id instanceof Identifier ? (Identifier) id : new Identifier(id.namespace(), id.identifier()); + public static T register(ResourceKey key, T item) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, key, item); + } } - public static void lock() { - if (!initialized) { - throw new IllegalStateException("cannot lock item registry unless it's been initialized!"); + @Deprecated + public static T register(int id, NamespacedIdentifier key, T item) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, id, key, item); } + } - locked = true; + public static void init() { + SyncedRegistries.register(RegistryKeys.ITEM); } public static void unlock() { - if (initialized) { - throw new IllegalStateException("cannot unlock item registry once it's been initialized!"); - } - locked = false; } - public static void init() { - if (locked) { - throw new IllegalStateException("cannot initialize item registry when it's locked!"); - } - + public static void registerItems() { ItemEvents.REGISTER_ITEMS.invoker().run(); - initialized = true; } } diff --git a/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/ItemsMixinPlugin.java b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/ItemsMixinPlugin.java new file mode 100644 index 000000000..5dc584a26 --- /dev/null +++ b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/ItemsMixinPlugin.java @@ -0,0 +1,52 @@ +package net.ornithemc.osl.items.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 ItemsMixinPlugin implements IMixinConfigPlugin { + + @Override + public void onLoad(String mixinPackage) { + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if ("net.ornithemc.osl.items.impl.mixin.client.ItemColorsMixin".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("16w02a") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.common.StatsMixinNew".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("15w33a") >= 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/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/item/ItemModelRegistryMapper.java b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/item/ItemModelRegistryMapper.java new file mode 100644 index 000000000..7cc467186 --- /dev/null +++ b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/item/ItemModelRegistryMapper.java @@ -0,0 +1,60 @@ +package net.ornithemc.osl.items.impl.item; + +import java.util.HashMap; +import java.util.Map; + +import net.ornithemc.osl.registries.api.registry.sync.IdMapper; +import net.ornithemc.osl.registries.api.registry.sync.RegistryMappings; + +public class ItemModelRegistryMapper implements IdMapper { + + public static ItemModelRegistryMapper of(Map registry) { + return new ItemModelRegistryMapper(registry); + } + + private static final int ID_SHIFT = 16; + private static final int METADATA_MASK = (1 << ID_SHIFT) - 1; + + private final Map registry; + private final Map backup; + + private boolean applied; + + @SuppressWarnings("unchecked") + private ItemModelRegistryMapper(Map registry) { + this.registry = (Map) registry; + this.backup = new HashMap<>(this.registry.size()); + } + + @Override + public void apply(RegistryMappings mappings) { + this.backup.clear(); + this.backup.putAll(this.registry); + + this.registry.clear(); + + for (Map.Entry e : this.backup.entrySet()) { + Object value = e.getValue(); + int index = e.getKey(); + int oldId = index >> ID_SHIFT; + int metadata = index & METADATA_MASK; + int newId = mappings.remap(oldId); + + if (newId >= 0) { + this.registry.put(newId << ID_SHIFT | metadata, value); + } + } + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + this.registry.clear(); + this.registry.putAll(this.backup); + } + + this.applied = false; + } +} diff --git a/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemColorsMixin.java b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemColorsMixin.java new file mode 100644 index 000000000..8273a3458 --- /dev/null +++ b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemColorsMixin.java @@ -0,0 +1,34 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +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.client.world.color.ItemColor; +import net.minecraft.client.world.color.ItemColors; +import net.minecraft.util.Id2ObjectBiMap; + +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(ItemColors.class) +public class ItemColorsMixin { + + @Shadow @Final + private Id2ObjectBiMap registry; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$registerModelRegistryMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("item_color"), Id2ObjectBiMapMapper.of(this.registry)); + } +} diff --git a/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemModelShaperMixin.java b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemModelShaperMixin.java new file mode 100644 index 000000000..b25d47e89 --- /dev/null +++ b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemModelShaperMixin.java @@ -0,0 +1,39 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import java.util.Map; + +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.client.render.item.ItemModelShaper; +import net.minecraft.client.resource.ModelIdentifier; +import net.minecraft.client.resource.model.BakedModel; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.items.impl.item.ItemModelRegistryMapper; +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.api.registry.SyncedRegistries; + +@Mixin(ItemModelShaper.class) +public class ItemModelShaperMixin { + + @Shadow @Final + private Map models; + @Shadow @Final + private Map modelCache; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$registerModelRegistryMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("item_model_location"), ItemModelRegistryMapper.of(this.models)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("item_model"), ItemModelRegistryMapper.of(this.modelCache)); + } +} diff --git a/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java index d50463e17..ab351b9fe 100644 --- a/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java +++ b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java @@ -1,17 +1,26 @@ package net.ornithemc.osl.items.impl.mixin.common; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import net.minecraft.item.Item; +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.impl.util.Util; +import net.ornithemc.osl.items.api.ItemRegistry; import net.ornithemc.osl.items.impl.ItemRegistryImpl; @Mixin(Item.class) public class ItemMixin { + @Shadow + private String key; + @Inject( method = "init", at = @At( @@ -28,8 +37,40 @@ public class ItemMixin { value = "TAIL" ) ) - private static void osl$items$initAndLockItemRegistry(CallbackInfo ci) { - ItemRegistryImpl.init(); - ItemRegistryImpl.lock(); + private static void osl$items$registerItems(CallbackInfo ci) { + ItemRegistryImpl.registerItems(); + } + + @Inject( + method = "getTranslationKey()Ljava/lang/String;", + at = @At( + value = "HEAD" + ) + ) + private void osl$items$autoAssignTranslationKey1(CallbackInfoReturnable cir) { + this.ensureTranslationKeyExists(); + } + + @Inject( + method = "getTranslationKey(Lnet/minecraft/item/ItemStack;)Ljava/lang/String;", + at = @At( + value = "HEAD" + ) + ) + private void osl$items$autoAssignTranslationKey2(CallbackInfoReturnable cir) { + this.ensureTranslationKeyExists(); + } + + @Unique + private void ensureTranslationKeyExists() { + if (this.key == null) { + NamespacedIdentifier identifier = ItemRegistry.getIdentifier((Item) (Object) this); + + if (identifier == null) { + this.key = "unknown"; + } else { + this.key = Util.makeTranslationKey(identifier); + } + } } } diff --git a/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/mixin/common/StatsMixin.java b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/mixin/common/StatsMixin.java new file mode 100644 index 000000000..6b530ac4b --- /dev/null +++ b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/mixin/common/StatsMixin.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.items.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.stat.Stat; +import net.minecraft.stat.Stats; + +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.ObjectArrayMapper; + +@Mixin(Stats.class) +public class StatsMixin { + + @Shadow @Final + private static Stat[] ITEMS_CRAFTED; + @Shadow @Final + private static Stat[] ITEMS_USED; + @Shadow @Final + private static Stat[] ITEMS_BROKEN; + + @Inject( + // inject at init instead of in case the arrays are resized... + method = "init", + at = @At( + value = "TAIL" + ) + ) + private static void osl$items$registerStatsMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("stats/crafted"), ObjectArrayMapper.of(ITEMS_CRAFTED)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("stats/used"), ObjectArrayMapper.of(ITEMS_USED)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("stats/broken"), ObjectArrayMapper.of(ITEMS_BROKEN)); + } +} diff --git a/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/mixin/common/StatsMixinNew.java b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/mixin/common/StatsMixinNew.java new file mode 100644 index 000000000..184ad42cb --- /dev/null +++ b/libraries/items/items-mc14w26a-mc17w46a/src/main/java/net/ornithemc/osl/items/impl/mixin/common/StatsMixinNew.java @@ -0,0 +1,37 @@ +package net.ornithemc.osl.items.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.stat.Stat; +import net.minecraft.stat.Stats; + +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.ObjectArrayMapper; + +@Mixin(Stats.class) +public class StatsMixinNew { + + @Shadow @Final + private static Stat[] ITEMS_PICKED_UP; + @Shadow @Final + private static Stat[] ITEMS_DROPPED; + + @Inject( + // inject at init instead of in case the arrays are resized... + method = "init", + at = @At( + value = "TAIL" + ) + ) + private static void osl$items$registerStatsMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("stats/picked_up"), ObjectArrayMapper.of(ITEMS_PICKED_UP)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("stats/dropped"), ObjectArrayMapper.of(ITEMS_DROPPED)); + } +} diff --git a/libraries/items/items-mc14w26a-mc17w46a/src/main/resources/fabric.mod.json b/libraries/items/items-mc14w26a-mc17w46a/src/main/resources/fabric.mod.json index f087b2afd..f7da14658 100644 --- a/libraries/items/items-mc14w26a-mc17w46a/src/main/resources/fabric.mod.json +++ b/libraries/items/items-mc14w26a-mc17w46a/src/main/resources/fabric.mod.json @@ -3,6 +3,11 @@ "id": "osl-items", "version": "0.1.0+mc14w26a-mc17w46a", "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.items.impl.ItemRegistryImpl::init" + ] + }, "mixins": [ "osl.items.mixins.json" ], @@ -11,6 +16,13 @@ "fabricloader": "\u003e\u003d0.18.0", "minecraft": "\u003e\u003d1.8-alpha.14.26.a \u003c\u003d1.13-alpha.17.46.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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0", + "osl-registries": "\u003e\u003d0.1.0-", "osl-blocks": "\u003e\u003d0.1.0" }, "name": "OSL Items", diff --git a/libraries/items/items-mc14w26a-mc17w46a/src/main/resources/osl.items.mixins.json b/libraries/items/items-mc14w26a-mc17w46a/src/main/resources/osl.items.mixins.json index eba99f927..16954f366 100644 --- a/libraries/items/items-mc14w26a-mc17w46a/src/main/resources/osl.items.mixins.json +++ b/libraries/items/items-mc14w26a-mc17w46a/src/main/resources/osl.items.mixins.json @@ -3,10 +3,15 @@ "minVersion": "0.8", "package": "net.ornithemc.osl.items.impl.mixin", "compatibilityLevel": "JAVA_8", + "plugin": "net.ornithemc.osl.items.impl.ItemsMixinPlugin", "mixins": [ - "common.ItemMixin" + "common.ItemMixin", + "common.StatsMixin", + "common.StatsMixinNew" ], "client": [ + "client.ItemColorsMixin", + "client.ItemModelShaperMixin" ], "server": [ ], diff --git a/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java b/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java index fc2acc8bf..848e4a19a 100644 --- a/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java +++ b/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java @@ -8,12 +8,16 @@ import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.items.impl.ItemRegistryImpl; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; /** * Public access to the Items registry. */ public final class ItemRegistry { + public static final Registry REGISTRY = ItemRegistryImpl.REGISTRY; + /** * @return the numerical ID assigned to the given item. */ @@ -24,7 +28,14 @@ public static int getId(Item item) { /** * @return the namespaced ID assigned to the given item. */ - public static NamespacedIdentifier getKey(Item item) { + public static NamespacedIdentifier getIdentifier(Item item) { + return ItemRegistryImpl.getIdentifier(item); + } + + /** + * @return the resource key assigned to the given item. + */ + public static ResourceKey getKey(Item item) { return ItemRegistryImpl.getKey(item); } @@ -38,14 +49,35 @@ public static Item getItem(int id) { /** * @return the item mapped to the given namespaced ID. */ - public static Item getItem(NamespacedIdentifier key) { + public static Item getItem(NamespacedIdentifier identifier) { + return ItemRegistryImpl.getItem(identifier); + } + + /** + * @return the item mapped to the given resource key. + */ + public static Item getItem(ResourceKey key) { return ItemRegistryImpl.getItem(key); } + /** + * @return the item mapped to the given block. + */ + public static Item getItem(Block block) { + return ItemRegistryImpl.getItem(block); + } + /** * @return a set containing all namespaced IDs in the registry. */ - public static Set keySet() { + public static Set identifierSet() { + return ItemRegistryImpl.identifierSet(); + } + + /** + * @return a set containing all resource keys in the registry. + */ + public static Set> keySet() { return ItemRegistryImpl.keySet(); } @@ -76,13 +108,23 @@ public static T register(Block block, T item) { return ItemRegistryImpl.register(block, item); } + /** + * @param the item type. + * @param identifier the namespaced ID of the item. + * @param item the item to register. + * @return the registered item. + */ + public static T register(NamespacedIdentifier identifier, T item) { + return ItemRegistryImpl.register(identifier, item); + } + /** * @param the item type. - * @param key the namespaced ID of the item. + * @param key the resource key of the item. * @param item the item to register. * @return the registered item. */ - public static T register(NamespacedIdentifier key, T item) { + public static T register(ResourceKey key, T item) { return ItemRegistryImpl.register(key, item); } } diff --git a/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java b/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java index 484c47ced..565b6583d 100644 --- a/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java +++ b/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java @@ -1,40 +1,60 @@ package net.ornithemc.osl.items.impl; -import java.util.Collections; import java.util.Set; import net.minecraft.block.Block; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; -import net.minecraft.resource.Identifier; import net.ornithemc.osl.blocks.api.BlockRegistry; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.items.api.ItemEvents; +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 ItemRegistryImpl { + public static final Registry REGISTRY = VanillaRegistries.registerSimple(RegistryKeys.ITEM, Item.REGISTRY); + private static boolean locked = true; - private static boolean initialized = false; public static int getId(Item item) { - return Item.REGISTRY.getId(item); + return REGISTRY.getId(item); + } + + public static NamespacedIdentifier getIdentifier(Item item) { + return REGISTRY.getIdentifier(item); } - public static NamespacedIdentifier getKey(Item item) { - return Item.REGISTRY.getKey(item); + public static ResourceKey getKey(Item item) { + return REGISTRY.getKey(item); } public static Item getItem(int id) { - return Item.REGISTRY.get(id); + return REGISTRY.get(id); + } + + public static Item getItem(NamespacedIdentifier identifier) { + return REGISTRY.get(identifier); + } + + public static Item getItem(ResourceKey key) { + return REGISTRY.get(key); + } + + public static Item getItem(Block block) { + return Item.byBlock(block); } - public static Item getItem(NamespacedIdentifier key) { - return Item.REGISTRY.get(identifier(key)); + public static Set identifierSet() { + return REGISTRY.identifierSet(); } - public static Set keySet() { - return Collections.unmodifiableSet(Item.REGISTRY.entrySet()); + public static Set> keySet() { + return REGISTRY.keySet(); } public static BlockItem register(Block block) { @@ -46,49 +66,55 @@ public static T register(T item) { } public static T register(Block block, T item) { - return register(BlockRegistry.getKey(block), item); + return register(BlockRegistry.getIdentifier(block), item); } - public static T register(NamespacedIdentifier key, T item) { + public static T register(NamespacedIdentifier identifier, T item) { if (locked) { - throw new IllegalStateException("register called too " + (initialized ? "late" : "early") + ": registry locked!"); + throw new IllegalStateException("register called too early: registry locked!"); } else { if (item instanceof BlockItem) { ((BlockItem) item).register(Item.BLOCK_ITEMS, item); } - Item.REGISTRY.put(identifier(key), item); + return Registry.register(REGISTRY, identifier, item); } - - return item; } - private static Identifier identifier(NamespacedIdentifier id) { - return id instanceof Identifier ? (Identifier) id : new Identifier(id.namespace(), id.identifier()); + public static T register(ResourceKey key, T item) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + if (item instanceof BlockItem) { + ((BlockItem) item).register(Item.BLOCK_ITEMS, item); + } + + return Registry.register(REGISTRY, key, item); + } } - public static void lock() { - if (!initialized) { - throw new IllegalStateException("cannot lock item registry unless it's been initialized!"); + @Deprecated + public static T register(int id, NamespacedIdentifier key, T item) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + if (item instanceof BlockItem) { + ((BlockItem) item).register(Item.BLOCK_ITEMS, item); + } + + return Registry.register(REGISTRY, id, key, item); } + } - locked = true; + public static void init() { + SyncedRegistries.register(RegistryKeys.ITEM); } public static void unlock() { - if (initialized) { - throw new IllegalStateException("cannot unlock item registry once it's been initialized!"); - } - locked = false; } - public static void init() { - if (locked) { - throw new IllegalStateException("cannot initialize item registry when it's locked!"); - } - + public static void registerItems() { ItemEvents.REGISTER_ITEMS.invoker().run(); - initialized = true; } } diff --git a/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemColorsMixin.java b/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemColorsMixin.java new file mode 100644 index 000000000..8273a3458 --- /dev/null +++ b/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemColorsMixin.java @@ -0,0 +1,34 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +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.client.world.color.ItemColor; +import net.minecraft.client.world.color.ItemColors; +import net.minecraft.util.Id2ObjectBiMap; + +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(ItemColors.class) +public class ItemColorsMixin { + + @Shadow @Final + private Id2ObjectBiMap registry; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$registerModelRegistryMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("item_color"), Id2ObjectBiMapMapper.of(this.registry)); + } +} diff --git a/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemModelShaperMixin.java b/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemModelShaperMixin.java new file mode 100644 index 000000000..4c607e061 --- /dev/null +++ b/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemModelShaperMixin.java @@ -0,0 +1,39 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +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 it.unimi.dsi.fastutil.ints.Int2ObjectMap; + +import net.minecraft.client.render.item.ItemModelShaper; +import net.minecraft.client.resource.ModelIdentifier; +import net.minecraft.client.resource.model.BakedModel; + +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.Int2ObjectMapMapper; + +@Mixin(ItemModelShaper.class) +public class ItemModelShaperMixin { + + @Shadow @Final + private Int2ObjectMap models; + @Shadow @Final + private Int2ObjectMap modelCache; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$registerModelRegistryMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("item_model_location"), Int2ObjectMapMapper.of(this.models)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("item_model"), Int2ObjectMapMapper.of(this.modelCache)); + } +} diff --git a/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java b/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java index d50463e17..7a15bfd05 100644 --- a/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java +++ b/libraries/items/items-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java @@ -28,8 +28,7 @@ public class ItemMixin { value = "TAIL" ) ) - private static void osl$items$initAndLockItemRegistry(CallbackInfo ci) { - ItemRegistryImpl.init(); - ItemRegistryImpl.lock(); + private static void osl$items$registerItems(CallbackInfo ci) { + ItemRegistryImpl.registerItems(); } } diff --git a/libraries/items/items-mc17w47a-mc18w31a/src/main/resources/fabric.mod.json b/libraries/items/items-mc17w47a-mc18w31a/src/main/resources/fabric.mod.json index 0d51ecd14..9e138ffd0 100644 --- a/libraries/items/items-mc17w47a-mc18w31a/src/main/resources/fabric.mod.json +++ b/libraries/items/items-mc17w47a-mc18w31a/src/main/resources/fabric.mod.json @@ -3,6 +3,11 @@ "id": "osl-items", "version": "0.1.0+mc17w47a-mc18w31a", "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.items.impl.ItemRegistryImpl::init" + ] + }, "mixins": [ "osl.items.mixins.json" ], @@ -10,6 +15,13 @@ "fabricloader": "\u003e\u003d0.18.0", "minecraft": "\u003e\u003d1.13-alpha.17.47.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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0", + "osl-registries": "\u003e\u003d0.1.0-", "osl-blocks": "\u003e\u003d0.1.0" }, "name": "OSL Items", diff --git a/libraries/items/items-mc17w47a-mc18w31a/src/main/resources/osl.items.mixins.json b/libraries/items/items-mc17w47a-mc18w31a/src/main/resources/osl.items.mixins.json index eba99f927..5263915ed 100644 --- a/libraries/items/items-mc17w47a-mc18w31a/src/main/resources/osl.items.mixins.json +++ b/libraries/items/items-mc17w47a-mc18w31a/src/main/resources/osl.items.mixins.json @@ -7,6 +7,8 @@ "common.ItemMixin" ], "client": [ + "client.ItemColorsMixin", + "client.ItemModelShaperMixin" ], "server": [ ], diff --git a/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java b/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java index fc2acc8bf..848e4a19a 100644 --- a/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java +++ b/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java @@ -8,12 +8,16 @@ import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.items.impl.ItemRegistryImpl; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; /** * Public access to the Items registry. */ public final class ItemRegistry { + public static final Registry REGISTRY = ItemRegistryImpl.REGISTRY; + /** * @return the numerical ID assigned to the given item. */ @@ -24,7 +28,14 @@ public static int getId(Item item) { /** * @return the namespaced ID assigned to the given item. */ - public static NamespacedIdentifier getKey(Item item) { + public static NamespacedIdentifier getIdentifier(Item item) { + return ItemRegistryImpl.getIdentifier(item); + } + + /** + * @return the resource key assigned to the given item. + */ + public static ResourceKey getKey(Item item) { return ItemRegistryImpl.getKey(item); } @@ -38,14 +49,35 @@ public static Item getItem(int id) { /** * @return the item mapped to the given namespaced ID. */ - public static Item getItem(NamespacedIdentifier key) { + public static Item getItem(NamespacedIdentifier identifier) { + return ItemRegistryImpl.getItem(identifier); + } + + /** + * @return the item mapped to the given resource key. + */ + public static Item getItem(ResourceKey key) { return ItemRegistryImpl.getItem(key); } + /** + * @return the item mapped to the given block. + */ + public static Item getItem(Block block) { + return ItemRegistryImpl.getItem(block); + } + /** * @return a set containing all namespaced IDs in the registry. */ - public static Set keySet() { + public static Set identifierSet() { + return ItemRegistryImpl.identifierSet(); + } + + /** + * @return a set containing all resource keys in the registry. + */ + public static Set> keySet() { return ItemRegistryImpl.keySet(); } @@ -76,13 +108,23 @@ public static T register(Block block, T item) { return ItemRegistryImpl.register(block, item); } + /** + * @param the item type. + * @param identifier the namespaced ID of the item. + * @param item the item to register. + * @return the registered item. + */ + public static T register(NamespacedIdentifier identifier, T item) { + return ItemRegistryImpl.register(identifier, item); + } + /** * @param the item type. - * @param key the namespaced ID of the item. + * @param key the resource key of the item. * @param item the item to register. * @return the registered item. */ - public static T register(NamespacedIdentifier key, T item) { + public static T register(ResourceKey key, T item) { return ItemRegistryImpl.register(key, item); } } diff --git a/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java b/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java index 99878100c..d6bd9a2bc 100644 --- a/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java +++ b/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java @@ -1,41 +1,60 @@ package net.ornithemc.osl.items.impl; -import java.util.Collections; import java.util.Set; import net.minecraft.block.Block; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; -import net.minecraft.resource.Identifier; -import net.minecraft.util.registry.Registry; import net.ornithemc.osl.blocks.api.BlockRegistry; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.items.api.ItemEvents; +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 ItemRegistryImpl { + public static final Registry REGISTRY = VanillaRegistries.registerSimple(RegistryKeys.ITEM, net.minecraft.util.registry.Registry.ITEM); + private static boolean locked = true; - private static boolean initialized = false; public static int getId(Item item) { - return Registry.ITEM.getId(item); + return REGISTRY.getId(item); + } + + public static NamespacedIdentifier getIdentifier(Item item) { + return REGISTRY.getIdentifier(item); } - public static NamespacedIdentifier getKey(Item item) { - return Registry.ITEM.getKey(item); + public static ResourceKey getKey(Item item) { + return REGISTRY.getKey(item); } public static Item getItem(int id) { - return Registry.ITEM.get(id); + return REGISTRY.get(id); + } + + public static Item getItem(NamespacedIdentifier identifier) { + return REGISTRY.get(identifier); + } + + public static Item getItem(ResourceKey key) { + return REGISTRY.get(key); + } + + public static Item getItem(Block block) { + return Item.byBlock(block); } - public static Item getItem(NamespacedIdentifier key) { - return Registry.ITEM.get(identifier(key)); + public static Set identifierSet() { + return REGISTRY.identifierSet(); } - public static Set keySet() { - return Collections.unmodifiableSet(Registry.ITEM.keySet()); + public static Set> keySet() { + return REGISTRY.keySet(); } public static BlockItem register(Block block) { @@ -47,49 +66,55 @@ public static T register(T item) { } public static T register(Block block, T item) { - return register(BlockRegistry.getKey(block), item); + return register(BlockRegistry.getIdentifier(block), item); } - public static T register(NamespacedIdentifier key, T item) { + public static T register(NamespacedIdentifier identifier, T item) { if (locked) { - throw new IllegalStateException("register called too " + (initialized ? "late" : "early") + ": registry locked!"); + throw new IllegalStateException("register called too early: registry locked!"); } else { if (item instanceof BlockItem) { ((BlockItem) item).register(Item.BLOCK_ITEMS, item); } - Registry.ITEM.register(identifier(key), item); + return Registry.register(REGISTRY, identifier, item); } - - return item; } - private static Identifier identifier(NamespacedIdentifier id) { - return id instanceof Identifier ? (Identifier) id : new Identifier(id.namespace(), id.identifier()); + public static T register(ResourceKey key, T item) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + if (item instanceof BlockItem) { + ((BlockItem) item).register(Item.BLOCK_ITEMS, item); + } + + return Registry.register(REGISTRY, key, item); + } } - public static void lock() { - if (!initialized) { - throw new IllegalStateException("cannot lock item registry unless it's been initialized!"); + @Deprecated + public static T register(int id, NamespacedIdentifier key, T item) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + if (item instanceof BlockItem) { + ((BlockItem) item).register(Item.BLOCK_ITEMS, item); + } + + return Registry.register(REGISTRY, id, key, item); } + } - locked = true; + public static void init() { + SyncedRegistries.register(RegistryKeys.ITEM); } public static void unlock() { - if (initialized) { - throw new IllegalStateException("cannot unlock item registry once it's been initialized!"); - } - locked = false; } - public static void init() { - if (locked) { - throw new IllegalStateException("cannot initialize item registry when it's locked!"); - } - + public static void registerItems() { ItemEvents.REGISTER_ITEMS.invoker().run(); - initialized = true; } } diff --git a/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemColorsMixin.java b/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemColorsMixin.java new file mode 100644 index 000000000..8273a3458 --- /dev/null +++ b/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemColorsMixin.java @@ -0,0 +1,34 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +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.client.world.color.ItemColor; +import net.minecraft.client.world.color.ItemColors; +import net.minecraft.util.Id2ObjectBiMap; + +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(ItemColors.class) +public class ItemColorsMixin { + + @Shadow @Final + private Id2ObjectBiMap registry; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$registerModelRegistryMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("item_color"), Id2ObjectBiMapMapper.of(this.registry)); + } +} diff --git a/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemModelShaperMixin.java b/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemModelShaperMixin.java new file mode 100644 index 000000000..4c607e061 --- /dev/null +++ b/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemModelShaperMixin.java @@ -0,0 +1,39 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +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 it.unimi.dsi.fastutil.ints.Int2ObjectMap; + +import net.minecraft.client.render.item.ItemModelShaper; +import net.minecraft.client.resource.ModelIdentifier; +import net.minecraft.client.resource.model.BakedModel; + +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.Int2ObjectMapMapper; + +@Mixin(ItemModelShaper.class) +public class ItemModelShaperMixin { + + @Shadow @Final + private Int2ObjectMap models; + @Shadow @Final + private Int2ObjectMap modelCache; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$registerModelRegistryMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("item_model_location"), Int2ObjectMapMapper.of(this.models)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("item_model"), Int2ObjectMapMapper.of(this.modelCache)); + } +} diff --git a/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java b/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java index d50463e17..7a15bfd05 100644 --- a/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java +++ b/libraries/items/items-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java @@ -28,8 +28,7 @@ public class ItemMixin { value = "TAIL" ) ) - private static void osl$items$initAndLockItemRegistry(CallbackInfo ci) { - ItemRegistryImpl.init(); - ItemRegistryImpl.lock(); + private static void osl$items$registerItems(CallbackInfo ci) { + ItemRegistryImpl.registerItems(); } } diff --git a/libraries/items/items-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json b/libraries/items/items-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json index c164da2c6..24a30ab9a 100644 --- a/libraries/items/items-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json +++ b/libraries/items/items-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json @@ -3,6 +3,11 @@ "id": "osl-items", "version": "0.1.0+mc18w32a-mc1.13.2", "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.items.impl.ItemRegistryImpl::init" + ] + }, "mixins": [ "osl.items.mixins.json" ], @@ -10,6 +15,13 @@ "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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0", + "osl-registries": "\u003e\u003d0.1.0-", "osl-blocks": "\u003e\u003d0.1.0" }, "name": "OSL Items", diff --git a/libraries/items/items-mc18w32a-mc1.13.2/src/main/resources/osl.items.mixins.json b/libraries/items/items-mc18w32a-mc1.13.2/src/main/resources/osl.items.mixins.json index eba99f927..5263915ed 100644 --- a/libraries/items/items-mc18w32a-mc1.13.2/src/main/resources/osl.items.mixins.json +++ b/libraries/items/items-mc18w32a-mc1.13.2/src/main/resources/osl.items.mixins.json @@ -7,6 +7,8 @@ "common.ItemMixin" ], "client": [ + "client.ItemColorsMixin", + "client.ItemModelShaperMixin" ], "server": [ ], diff --git a/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java b/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java index fc2acc8bf..848e4a19a 100644 --- a/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java +++ b/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java @@ -8,12 +8,16 @@ import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.items.impl.ItemRegistryImpl; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; /** * Public access to the Items registry. */ public final class ItemRegistry { + public static final Registry REGISTRY = ItemRegistryImpl.REGISTRY; + /** * @return the numerical ID assigned to the given item. */ @@ -24,7 +28,14 @@ public static int getId(Item item) { /** * @return the namespaced ID assigned to the given item. */ - public static NamespacedIdentifier getKey(Item item) { + public static NamespacedIdentifier getIdentifier(Item item) { + return ItemRegistryImpl.getIdentifier(item); + } + + /** + * @return the resource key assigned to the given item. + */ + public static ResourceKey getKey(Item item) { return ItemRegistryImpl.getKey(item); } @@ -38,14 +49,35 @@ public static Item getItem(int id) { /** * @return the item mapped to the given namespaced ID. */ - public static Item getItem(NamespacedIdentifier key) { + public static Item getItem(NamespacedIdentifier identifier) { + return ItemRegistryImpl.getItem(identifier); + } + + /** + * @return the item mapped to the given resource key. + */ + public static Item getItem(ResourceKey key) { return ItemRegistryImpl.getItem(key); } + /** + * @return the item mapped to the given block. + */ + public static Item getItem(Block block) { + return ItemRegistryImpl.getItem(block); + } + /** * @return a set containing all namespaced IDs in the registry. */ - public static Set keySet() { + public static Set identifierSet() { + return ItemRegistryImpl.identifierSet(); + } + + /** + * @return a set containing all resource keys in the registry. + */ + public static Set> keySet() { return ItemRegistryImpl.keySet(); } @@ -76,13 +108,23 @@ public static T register(Block block, T item) { return ItemRegistryImpl.register(block, item); } + /** + * @param the item type. + * @param identifier the namespaced ID of the item. + * @param item the item to register. + * @return the registered item. + */ + public static T register(NamespacedIdentifier identifier, T item) { + return ItemRegistryImpl.register(identifier, item); + } + /** * @param the item type. - * @param key the namespaced ID of the item. + * @param key the resource key of the item. * @param item the item to register. * @return the registered item. */ - public static T register(NamespacedIdentifier key, T item) { + public static T register(ResourceKey key, T item) { return ItemRegistryImpl.register(key, item); } } diff --git a/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java b/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java index 8bc9e720d..d6bd9a2bc 100644 --- a/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java +++ b/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java @@ -1,41 +1,60 @@ package net.ornithemc.osl.items.impl; -import java.util.Collections; import java.util.Set; import net.minecraft.block.Block; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; -import net.minecraft.resource.Identifier; -import net.minecraft.util.registry.Registry; import net.ornithemc.osl.blocks.api.BlockRegistry; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.items.api.ItemEvents; +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 ItemRegistryImpl { + public static final Registry REGISTRY = VanillaRegistries.registerSimple(RegistryKeys.ITEM, net.minecraft.util.registry.Registry.ITEM); + private static boolean locked = true; - private static boolean initialized = false; public static int getId(Item item) { - return Registry.ITEM.getId(item); + return REGISTRY.getId(item); + } + + public static NamespacedIdentifier getIdentifier(Item item) { + return REGISTRY.getIdentifier(item); } - public static NamespacedIdentifier getKey(Item item) { - return Registry.ITEM.getKey(item); + public static ResourceKey getKey(Item item) { + return REGISTRY.getKey(item); } public static Item getItem(int id) { - return Registry.ITEM.get(id); + return REGISTRY.get(id); + } + + public static Item getItem(NamespacedIdentifier identifier) { + return REGISTRY.get(identifier); + } + + public static Item getItem(ResourceKey key) { + return REGISTRY.get(key); } - public static Item getItem(NamespacedIdentifier key) { - return Registry.ITEM.getOrDefault(identifier(key)); + public static Item getItem(Block block) { + return Item.byBlock(block); } - public static Set keySet() { - return Collections.unmodifiableSet(Registry.ITEM.keySet()); + public static Set identifierSet() { + return REGISTRY.identifierSet(); + } + + public static Set> keySet() { + return REGISTRY.keySet(); } public static BlockItem register(Block block) { @@ -47,47 +66,55 @@ public static T register(T item) { } public static T register(Block block, T item) { - return register(BlockRegistry.getKey(block), item); + return register(BlockRegistry.getIdentifier(block), item); } - public static T register(NamespacedIdentifier key, T item) { + public static T register(NamespacedIdentifier identifier, T item) { if (locked) { - throw new IllegalStateException("register called too " + (initialized ? "late" : "early") + ": registry locked!"); + throw new IllegalStateException("register called too early: registry locked!"); } else { if (item instanceof BlockItem) { ((BlockItem) item).register(Item.BLOCK_ITEMS, item); } - return Registry.ITEM.m_30368144(identifier(key), item); + return Registry.register(REGISTRY, identifier, item); } } - private static Identifier identifier(NamespacedIdentifier id) { - return id instanceof Identifier ? (Identifier) id : new Identifier(id.namespace(), id.identifier()); + public static T register(ResourceKey key, T item) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + if (item instanceof BlockItem) { + ((BlockItem) item).register(Item.BLOCK_ITEMS, item); + } + + return Registry.register(REGISTRY, key, item); + } } - public static void lock() { - if (!initialized) { - throw new IllegalStateException("cannot lock item registry unless it's been initialized!"); + @Deprecated + public static T register(int id, NamespacedIdentifier key, T item) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + if (item instanceof BlockItem) { + ((BlockItem) item).register(Item.BLOCK_ITEMS, item); + } + + return Registry.register(REGISTRY, id, key, item); } + } - locked = true; + public static void init() { + SyncedRegistries.register(RegistryKeys.ITEM); } public static void unlock() { - if (initialized) { - throw new IllegalStateException("cannot unlock item registry once it's been initialized!"); - } - locked = false; } - public static void init() { - if (locked) { - throw new IllegalStateException("cannot initialize item registry when it's locked!"); - } - + public static void registerItems() { ItemEvents.REGISTER_ITEMS.invoker().run(); - initialized = true; } } diff --git a/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemColorsMixin.java b/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemColorsMixin.java new file mode 100644 index 000000000..8273a3458 --- /dev/null +++ b/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemColorsMixin.java @@ -0,0 +1,34 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +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.client.world.color.ItemColor; +import net.minecraft.client.world.color.ItemColors; +import net.minecraft.util.Id2ObjectBiMap; + +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(ItemColors.class) +public class ItemColorsMixin { + + @Shadow @Final + private Id2ObjectBiMap registry; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$registerModelRegistryMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("item_color"), Id2ObjectBiMapMapper.of(this.registry)); + } +} diff --git a/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemModelShaperMixin.java b/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemModelShaperMixin.java new file mode 100644 index 000000000..4c607e061 --- /dev/null +++ b/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemModelShaperMixin.java @@ -0,0 +1,39 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +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 it.unimi.dsi.fastutil.ints.Int2ObjectMap; + +import net.minecraft.client.render.item.ItemModelShaper; +import net.minecraft.client.resource.ModelIdentifier; +import net.minecraft.client.resource.model.BakedModel; + +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.Int2ObjectMapMapper; + +@Mixin(ItemModelShaper.class) +public class ItemModelShaperMixin { + + @Shadow @Final + private Int2ObjectMap models; + @Shadow @Final + private Int2ObjectMap modelCache; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$registerModelRegistryMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("item_model_location"), Int2ObjectMapMapper.of(this.models)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("item_model"), Int2ObjectMapMapper.of(this.modelCache)); + } +} diff --git a/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemsMixin.java b/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemsMixin.java index 44264b2e5..85b048a10 100644 --- a/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemsMixin.java +++ b/libraries/items/items-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemsMixin.java @@ -28,8 +28,7 @@ public class ItemsMixin { value = "TAIL" ) ) - private static void osl$items$initAndLockItemRegistry(CallbackInfo ci) { - ItemRegistryImpl.init(); - ItemRegistryImpl.lock(); + private static void osl$items$registerItems(CallbackInfo ci) { + ItemRegistryImpl.registerItems(); } } diff --git a/libraries/items/items-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json b/libraries/items/items-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json index 4100f5897..4b1c9530d 100644 --- a/libraries/items/items-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json +++ b/libraries/items/items-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json @@ -3,6 +3,11 @@ "id": "osl-items", "version": "0.1.0+mc18w43a-mc1.14.4", "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.items.impl.ItemRegistryImpl::init" + ] + }, "mixins": [ "osl.items.mixins.json" ], @@ -10,6 +15,13 @@ "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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0", + "osl-registries": "\u003e\u003d0.1.0-", "osl-blocks": "\u003e\u003d0.1.0" }, "name": "OSL Items", diff --git a/libraries/items/items-mc18w43a-mc1.14.4/src/main/resources/osl.items.mixins.json b/libraries/items/items-mc18w43a-mc1.14.4/src/main/resources/osl.items.mixins.json index a0d26288a..8c5e33af9 100644 --- a/libraries/items/items-mc18w43a-mc1.14.4/src/main/resources/osl.items.mixins.json +++ b/libraries/items/items-mc18w43a-mc1.14.4/src/main/resources/osl.items.mixins.json @@ -7,6 +7,8 @@ "common.ItemsMixin" ], "client": [ + "client.ItemColorsMixin", + "client.ItemModelShaperMixin" ], "server": [ ], diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java index 5c9fdcbc3..0053bafcb 100644 --- a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/api/ItemRegistry.java @@ -8,6 +8,7 @@ import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.items.impl.ItemRegistryImpl; +import net.ornithemc.osl.registries.api.registry.ResourceKey; /** * Public access to the Items registry. @@ -24,7 +25,14 @@ public static int getId(Item item) { /** * @return the namespaced ID assigned to the given item. */ - public static NamespacedIdentifier getKey(Item item) { + public static NamespacedIdentifier getIdentifier(Item item) { + return ItemRegistryImpl.getIdentifier(item); + } + + /** + * @return the resource key assigned to the given item. + */ + public static ResourceKey getKey(Item item) { return ItemRegistryImpl.getKey(item); } @@ -38,14 +46,35 @@ public static Item getItem(int id) { /** * @return the item mapped to the given namespaced ID. */ - public static Item getItem(NamespacedIdentifier key) { + public static Item getItem(NamespacedIdentifier identifier) { + return ItemRegistryImpl.getItem(identifier); + } + + /** + * @return the item mapped to the given resource key. + */ + public static Item getItem(ResourceKey key) { return ItemRegistryImpl.getItem(key); } + /** + * @return the item mapped to the given block. + */ + public static Item getItem(Block block) { + return ItemRegistryImpl.getItem(block); + } + /** * @return a set containing all namespaced IDs in the registry. */ - public static Set keySet() { + public static Set identifierSet() { + return ItemRegistryImpl.identifierSet(); + } + + /** + * @return a set containing all resource keys in the registry. + */ + public static Set> keySet() { return ItemRegistryImpl.keySet(); } @@ -61,7 +90,10 @@ public static BlockItem register(Block block) { * @param the item type. * @param item the item to register. * @return the registered block item. + * + * @deprecated use {@linkplain #register(Block, Item)} instead. */ + @Deprecated public static T register(T item) { return ItemRegistryImpl.register(item); } @@ -76,13 +108,37 @@ public static T register(Block block, T item) { return ItemRegistryImpl.register(block, item); } + /** + * @param the item type. + * @param identifier the namespaced ID of the item. + * @param item the item to register. + * @return the registered item. + */ + public static T register(NamespacedIdentifier identifier, T item) { + return ItemRegistryImpl.register(identifier, item); + } + + /** + * @param the item type. + * @param key the resource key of the item. + * @param item the item to register. + * @return the registered item. + */ + public static T register(ResourceKey key, T item) { + return ItemRegistryImpl.register(key, item); + } + /** * @param the item type. * @param id the numerical ID of the item. * @param key the namespaced ID of the item. * @param item the item to register. * @return the registered item. + * + * @deprecated use {@linkplain #register(NamespacedIdentifier, Item)} + * or {@linkplain #register(ResourceKey, Item)} instead. */ + @Deprecated public static T register(int id, NamespacedIdentifier key, T item) { return ItemRegistryImpl.register(id, key, item); } diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/api/item/ItemExtension.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/api/item/ItemExtension.java index 947b09345..be234462b 100644 --- a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/api/item/ItemExtension.java +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/api/item/ItemExtension.java @@ -2,10 +2,12 @@ import net.minecraft.item.Item; -import net.ornithemc.osl.core.api.registry.SimpleIdRegistry; +import net.ornithemc.osl.items.impl.ItemRegistryImpl; +import net.ornithemc.osl.registries.api.registry.Registry; public interface ItemExtension { - SimpleIdRegistry REGISTRY = new SimpleIdRegistry<>(); + Registry REGISTRY = ItemRegistryImpl.REGISTRY; + int AUTO_ASSIGN_ID = -172172; } diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java index d7beeda93..1a0acbad6 100644 --- a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/ItemRegistryImpl.java @@ -10,39 +10,62 @@ import net.ornithemc.osl.blocks.api.BlockRegistry; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; import net.ornithemc.osl.items.api.ItemEvents; +import net.ornithemc.osl.items.impl.item.ItemIdFixer; import net.ornithemc.osl.items.impl.mixin.common.BlockItemAccess; +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 ItemRegistryImpl { + public static final Registry REGISTRY = Registries.registerSimple(RegistryKeys.ITEM, () -> { /* Item bootstrap is triggered by Block bootstrap */ }); public static final Map BLOCK_ITEMS = new HashMap<>(); private static boolean locked = true; - private static boolean itemsInitialized = false; - private static boolean blocksInitialized = false; public static int getId(Item item) { - return Item.REGISTRY.getId(item); + return REGISTRY.getId(item); } - public static NamespacedIdentifier getKey(Item item) { - return Item.REGISTRY.getKey(item); + public static NamespacedIdentifier getIdentifier(Item item) { + return REGISTRY.getIdentifier(item); + } + + public static ResourceKey getKey(Item item) { + return REGISTRY.getKey(item); } public static Item getItem(int id) { - return Item.REGISTRY.get(id); + return REGISTRY.get(id); + } + + public static Item getItem(NamespacedIdentifier identifier) { + return REGISTRY.get(identifier); + } + + public static Item getItem(ResourceKey key) { + return REGISTRY.get(key); } - public static Item getItem(NamespacedIdentifier key) { - return Item.REGISTRY.get(key); + public static Item getItem(Block block) { + return BLOCK_ITEMS.get(block); } - public static Set keySet() { - return Item.REGISTRY.keySet(); + public static Set identifierSet() { + return REGISTRY.identifierSet(); + } + + public static Set> keySet() { + return REGISTRY.keySet(); } public static BlockItem register(Block block) { - return register(block, new BlockItem(BlockRegistry.getId(block))); + return register(block, new BlockItem(Item.AUTO_ASSIGN_ID)); } public static T register(T item) { @@ -50,70 +73,83 @@ public static T register(T item) { } public static T register(Block block, T item) { + return register(BlockRegistry.getIdentifier(block), block, item); + } + + public static T register(NamespacedIdentifier identifier, Block block, T item) { if (!locked) { BLOCK_ITEMS.put(block, item); + + if (item instanceof BlockItem) { + ((BlockItemAccess) item).setBlock(block.id); + } } - return register(BlockRegistry.getId(block), BlockRegistry.getKey(block), item); + return register(identifier, item); } - public static T register(int id, NamespacedIdentifier key, T item) { + @SuppressWarnings("deprecation") + public static T register(NamespacedIdentifier identifier, T item) { if (locked) { - throw new IllegalStateException("register called too " + (itemsInitialized ? "late" : "early") + ": registry locked!"); + throw new IllegalStateException("register called too early: registry locked!"); } else { - Item.REGISTRY.register(id, key, item); + return Registry.register(REGISTRY, item.id, identifier, item); } + } - return item; + @SuppressWarnings("deprecation") + public static T register(ResourceKey key, T item) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + return Registry.register(REGISTRY, item.id, key, item); + } } - public static void lock() { - if (!itemsInitialized || !blocksInitialized) { - throw new IllegalStateException("cannot lock item registry unless it's been initialized!"); + @Deprecated + public static T register(int id, NamespacedIdentifier key, T item) { + if (locked) { + throw new IllegalStateException("register called too early: registry locked!"); + } else { + if (item.id != id) { + throw new IllegalArgumentException("ID " + id + " does not match item ID " + item.id + " for " + key); + } + + return Registry.register(REGISTRY, id, key, item); } + } - locked = true; + public static void init() { + SyncedRegistries.register(RegistryKeys.ITEM); + SyncedRegistries.registerFixer(RegistryKeys.ITEM, NamespacedIdentifiers.from("item/id"), new ItemIdFixer()); } public static void unlock() { - if (itemsInitialized || blocksInitialized) { - throw new IllegalStateException("cannot unlock item registry once it's been initialized!"); - } - locked = false; } - public static void initItems() { - if (locked) { - throw new IllegalStateException("cannot initialize items when the registry is locked!"); - } - + public static void registerItems() { VanillaItems.init(); - itemsInitialized = true; + ItemEvents.REGISTER_ITEMS.invoker().run(); } - public static void initBlocks() { - if (locked) { - throw new IllegalStateException("cannot initialize block items when the registry is locked!"); - } + public static void registerBlockItems() { + ItemEvents.REGISTER_BLOCK_ITEMS.invoker().run(); + } + public static void registerVanillaBlockItems() { + // must be invoked separately because most block items are auto-generated! VanillaBlockItems.init(); - blocksInitialized = true; } - public static void registerItems() { - if (locked) { - throw new IllegalStateException("cannot initialize item registry when it's locked!"); - } - - ItemEvents.REGISTER_ITEMS.invoker().run(); - } + public static void registerUnknownItems() { + for (Item item : Item.BY_ID) { + if (item != null && REGISTRY.getIdentifier(item) == null) { + NamespacedIdentifier identifier = NamespacedIdentifiers.from("osl", "item_" + item.id); - public static void registerBlocks() { - if (locked) { - throw new IllegalStateException("cannot initialize item registry when it's locked!"); + RegistriesImpl.LOGGER.warn("Item {}/{}", item.id, item.getClass().getSimpleName() + " was not registered to OSL's Item registry! Adding it as '" + identifier + "'..."); + ItemRegistryImpl.register(identifier, item); + } } - - ItemEvents.REGISTER_BLOCK_ITEMS.invoker().run(); } } diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/ItemsMixinPlugin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/ItemsMixinPlugin.java index 590562d92..e880731c5 100644 --- a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/ItemsMixinPlugin.java +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/ItemsMixinPlugin.java @@ -13,6 +13,9 @@ public class ItemsMixinPlugin implements IMixinConfigPlugin { public static final boolean STATS_EXIST = MinecraftVersion.resolve().compareTo("b1.4") >= 0; + public static final boolean RECIPES_OVERHAULED = MinecraftVersion.resolve().compareTo("b1.2") >= 0; + public static final boolean LOOT_ENTRIES_EXIST = MinecraftVersion.resolve().compareTo("b1.8-pre1") >= 0; + public static final boolean LOOT_ENTRY_USES_ITEM_STACK = MinecraftVersion.resolve().compareTo("12w50a") >= 0; @Override public void onLoad(String mixinPackage) { @@ -25,14 +28,107 @@ public String getRefMapperConfig() { @Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if ("net.ornithemc.osl.items.impl.mixin.client.CustomizeFlatWorldScreen_LayerListWidgetMixin".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("12w37a") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.client.MinecraftMixinNew".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("12w15a") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.client.MinecraftMixinMid".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("1.2.5") == 0; + } + if ("net.ornithemc.osl.items.impl.mixin.client.MinecraftMixinOld".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("b1.8-pre2") >= 0 && MinecraftVersion.resolve().compareTo("1.2.5") < 0; + } + if ("net.ornithemc.osl.items.impl.mixin.client.ItemRendererMixin_b1_4_01_12w34a_13w01a".equals(mixinClassName)) { + return (MinecraftVersion.resolve().compareTo("b1.5") < 0) || (MinecraftVersion.resolve().compareTo("12w34a") >= 0 && MinecraftVersion.resolve().compareTo("13w01a") <= 0); + } + if ("net.ornithemc.osl.items.impl.mixin.client.ItemRendererMixin_b1_5_12w32a".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("b1.5") >= 0 && MinecraftVersion.resolve().compareTo("12w32a") <= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.client.ItemRendererMixin_12w50a".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("12w50a") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.client.ItemRendererMixin_13w02a".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("13w02a") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.client.ItemRendererMixin_1_6".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("1.6") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.client.PlayerRendererMixin".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("a1.0.6") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.client.PlayerRendererMixinNew".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("a1.2.0") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.client.WitchRendererMixin".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("12w38a") >= 0; + } if ("net.ornithemc.osl.items.impl.mixin.common.ItemMixinNew".equals(mixinClassName) - || "net.ornithemc.osl.items.impl.mixin.common.BlockMixinNew".equals(mixinClassName)) { + || "net.ornithemc.osl.items.impl.mixin.common.ItemStatAccess".equals(mixinClassName) + || "net.ornithemc.osl.items.impl.mixin.common.BlockMixinNew".equals(mixinClassName) + || "net.ornithemc.osl.items.impl.mixin.common.StatsMixin".equals(mixinClassName) + || "net.ornithemc.osl.items.impl.mixin.common.AchievementsMixin".equals(mixinClassName)) { return STATS_EXIST; } if ("net.ornithemc.osl.items.impl.mixin.common.ItemMixinOld".equals(mixinClassName) || "net.ornithemc.osl.items.impl.mixin.common.BlockMixinOld".equals(mixinClassName)) { return !STATS_EXIST; } + if ("net.ornithemc.osl.items.impl.mixin.common.ItemStackMixinNew".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("b1.2") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.common.ShapedRecipeMixinNew".equals(mixinClassName) + || "net.ornithemc.osl.items.impl.mixin.common.ShapelessRecipeMixin".equals(mixinClassName) + || "net.ornithemc.osl.items.impl.mixin.common.SmeltingManagerMixin".equals(mixinClassName)) { + return RECIPES_OVERHAULED; + } + if ("net.ornithemc.osl.items.impl.mixin.common.ShapedRecipeMixinOld".equals(mixinClassName) + || "net.ornithemc.osl.items.impl.mixin.common.FurnaceBlockEntityMixinOld".equals(mixinClassName)) { + return !RECIPES_OVERHAULED; + } + if ("net.ornithemc.osl.items.impl.mixin.common.ItemMixin_1_3_1_13w01a".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("1.3.1") >= 0 && MinecraftVersion.resolve().compareTo("13w02a") < 0; + } + if ("net.ornithemc.osl.items.impl.mixin.common.ItemMixin_13w02a".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("13w02a") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.common.ItemMixin_b1_0_1_3".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("b1.0") >= 0 && MinecraftVersion.resolve().compareTo("1.3") <= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.common.FurnaceBlockEntityMixinNew".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("b1.5") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.common.SmeltingManagerMixinNew".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("12w30d") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.common.BlockMixin_SilkTouchDropItem".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("b1.9-pre6") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.client.BlockMixin_PickItem".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("12w15a") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.common.AxisBlockMixin".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("13w16a") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.common.LeavesBlockMixin".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("12w49a") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.common.PaneBlockMixin".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("12w17a") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.client.SlabBlockMixin".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("12w50a") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.common.QuartzBlockMixin".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("13w02a") >= 0; + } + if ("net.ornithemc.osl.items.impl.mixin.common.LootEntryMixinNew".equals(mixinClassName)) { + return LOOT_ENTRY_USES_ITEM_STACK; + } + if ("net.ornithemc.osl.items.impl.mixin.common.LootEntryMixinOld".equals(mixinClassName)) { + return LOOT_ENTRIES_EXIST && !LOOT_ENTRY_USES_ITEM_STACK; + } return true; } diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/LootEntryAccess.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/LootEntryAccess.java new file mode 100644 index 000000000..d9ef6a8d4 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/LootEntryAccess.java @@ -0,0 +1,13 @@ +package net.ornithemc.osl.items.impl; + +import net.minecraft.item.ItemStack; + +public interface LootEntryAccess { + + ItemStack osl$items$getItemStack(); + + int osl$items$getItem(); + + void osl$items$setItem(int item); + +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/VanillaBlockItems.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/VanillaBlockItems.java index 975769670..3f86916c9 100644 --- a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/VanillaBlockItems.java +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/VanillaBlockItems.java @@ -1,28 +1,43 @@ package net.ornithemc.osl.items.impl; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + import net.minecraft.block.Block; import net.minecraft.item.Item; + import net.ornithemc.osl.blocks.api.block.Blocks; import net.ornithemc.osl.blocks.impl.BlockRegistryImpl; +import net.ornithemc.osl.blocks.impl.VanillaBlocks; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.items.impl.item.ItemUtil; -final class VanillaBlockItems { +public final class VanillaBlockItems { + + public static final int MAX_ID = VanillaBlocks.MAX_ID; static void init() { - for (int id = 0; id < VanillaItems.ITEM_ID_OFFSET; id++) { - Block block = Block.BY_ID[id]; - Item item = Item.BY_ID[id]; - - if (block != Blocks.AIR && item != null) { - NamespacedIdentifier key = BlockRegistryImpl.getKey(block); - - if (ItemRegistryImpl.getItem(key) == null) { - ItemRegistryImpl.register(block, item); - } else { - // some blocks have both a block item and special item form - // we should handle that in some way, but how? TODO + for (Field f : Block.class.getDeclaredFields()) { + if (Modifier.isStatic(f.getModifiers()) && Block.class.isAssignableFrom(f.getType())) { + try { + Block block = (Block) f.get(null); + Item item = Item.BY_ID[block.id]; + + if (block != Blocks.AIR && item != null) { + NamespacedIdentifier identifier = BlockRegistryImpl.getIdentifier(block); + + if (ItemRegistryImpl.getItem(identifier) != null) { + // some blocks have both a block item and special item form + identifier = identifier.suffixed("_block"); + } + + ItemRegistryImpl.register(identifier, block, item); + } + } catch (Throwable t) { } } } + + ItemUtil.blockItemsInitialized = true; } } diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/VanillaItems.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/VanillaItems.java index 63e9a9621..08f9a540e 100644 --- a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/VanillaItems.java +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/VanillaItems.java @@ -7,7 +7,7 @@ import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; -final class VanillaItems { +public final class VanillaItems { /** * Namespaced IDs were introduced in 1.7. Before then, the numerical IDs @@ -220,8 +220,8 @@ final class VanillaItems { "record_wait" }; - static final int ITEM_ID_OFFSET = 256; - static final int DISC_ITEM_ID_OFFSET = 2000 + ITEM_ID_OFFSET; + public static final int ITEM_ID_OFFSET = VanillaBlockItems.MAX_ID + 1; + public static final int DISC_ITEM_ID_OFFSET = ITEM_ID_OFFSET + 2000; static void init() { for (Field f : Item.class.getDeclaredFields()) { @@ -230,29 +230,33 @@ static void init() { Item item = (Item) f.get(null); if (item != null) { - String identifier = null; + register(item); + } + } catch (Throwable t) { + } + } + } + } - if (item.id >= DISC_ITEM_ID_OFFSET) { - int id = item.id - DISC_ITEM_ID_OFFSET; + private static void register(Item item) { + String identifier = null; - if (id >= 0 && id < DISC_IDENTIFIERS.length) { - identifier = DISC_IDENTIFIERS[id]; - } - } else if (item.id >= ITEM_ID_OFFSET) { - int id = item.id - ITEM_ID_OFFSET; + if (item.id >= DISC_ITEM_ID_OFFSET) { + int id = item.id - DISC_ITEM_ID_OFFSET; - if (id >= 0 && id < IDENTIFIERS.length) { - identifier = IDENTIFIERS[id]; - } - } + if (id >= 0 && id < DISC_IDENTIFIERS.length) { + identifier = DISC_IDENTIFIERS[id]; + } + } else if (item.id >= ITEM_ID_OFFSET) { + int id = item.id - ITEM_ID_OFFSET; - if (identifier != null) { - ItemRegistryImpl.register(item.id, NamespacedIdentifiers.from(identifier), item); - } - } - } catch (Throwable t) { - } + if (id >= 0 && id < IDENTIFIERS.length) { + identifier = IDENTIFIERS[id]; } } + + if (identifier != null) { + ItemRegistryImpl.register(NamespacedIdentifiers.from(identifier), item); + } } } diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/AchievementsIconMapper.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/AchievementsIconMapper.java new file mode 100644 index 000000000..b8e38aaf3 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/AchievementsIconMapper.java @@ -0,0 +1,65 @@ +package net.ornithemc.osl.items.impl.item; + +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Set; + +import it.unimi.dsi.fastutil.ints.Int2IntFunction; + +import net.minecraft.stat.achievement.AchievementStat; + +import net.ornithemc.osl.registries.api.registry.sync.IdMapper; +import net.ornithemc.osl.registries.api.registry.sync.RegistryMappings; + +public class AchievementsIconMapper implements IdMapper { + + public static AchievementsIconMapper of(List achievements) { + return new AchievementsIconMapper(achievements); + } + + private final List achievements; + private final Set missing; + + private boolean applied; + + private AchievementsIconMapper(List achievements) { + this.achievements = achievements; + this.missing = Collections.newSetFromMap(new IdentityHashMap<>()); + } + + @Override + public void apply(RegistryMappings mappings) { + this.missing.clear(); + this.fixAchievementIcons(mappings::remap, true); + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + this.fixAchievementIcons(mappings::unmap, false); + this.missing.clear(); + } + + this.applied = false; + } + + private void fixAchievementIcons(Int2IntFunction mapper, boolean storeMissing) { + for (AchievementStat achievement : this.achievements) { + if (this.missing.contains(achievement)) { + continue; + } + + int oldId = achievement.icon.id; + int newId = mapper.applyAsInt(oldId); + + if (newId >= 0) { + achievement.icon.id = newId; + } else if (storeMissing) { + this.missing.add(achievement); + } + } + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/CraftingRecipesMapper.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/CraftingRecipesMapper.java new file mode 100644 index 000000000..1ebc4afc0 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/CraftingRecipesMapper.java @@ -0,0 +1,79 @@ +package net.ornithemc.osl.items.impl.item; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +import net.ornithemc.osl.items.impl.item.FixableRecipe.ItemMapper; +import net.ornithemc.osl.registries.api.registry.sync.IdMapper; +import net.ornithemc.osl.registries.api.registry.sync.RegistryMappings; + +public class CraftingRecipesMapper implements IdMapper { + + public static CraftingRecipesMapper of(List recipes, Comparator sorter) { + return new CraftingRecipesMapper(recipes, sorter); + } + + private final List recipes; + private final List missing; + private final Comparator sorter; + + private boolean applied; + + @SuppressWarnings("unchecked") + private CraftingRecipesMapper(List recipes, Comparator sorter) { + this.recipes = (List) recipes; + this.missing = new ArrayList<>(); + this.sorter = (Comparator) sorter; + } + + @Override + public void apply(RegistryMappings mappings) { + this.missing.clear(); + this.fixRecipes(mappings::remap, true); + + Collections.sort(this.recipes, this.sorter); + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + this.fixRecipes(mappings::unmap, false); + this.recipes.addAll(missing); + + Collections.sort(this.recipes, this.sorter); + } + + this.applied = false; + } + + private void fixRecipes(ItemMapper mapper, boolean storeMissing) { + Iterator it = this.recipes.iterator(); + + while (it.hasNext()) { + Object recipe = it.next(); + + if (this.canFixRecipe(mapper, recipe)) { + this.fixRecipe(mapper, recipe); + } else { + it.remove(); + + if (storeMissing) { + this.missing.add(recipe); + } + } + } + } + + private boolean canFixRecipe(ItemMapper mapper, Object recipe) { + return recipe instanceof FixableRecipe && ((FixableRecipe) recipe).osl$items$canFixRecipe(mapper); + } + + private void fixRecipe(ItemMapper mapper, Object recipe) { + ((FixableRecipe) recipe).osl$items$fixRecipe(mapper); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/FixableRecipe.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/FixableRecipe.java new file mode 100644 index 000000000..f6008a267 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/FixableRecipe.java @@ -0,0 +1,27 @@ +package net.ornithemc.osl.items.impl.item; + +import net.minecraft.item.ItemStack; + +public interface FixableRecipe { + + boolean osl$items$canFixRecipe(ItemMapper mapper); + + void osl$items$fixRecipe(ItemMapper mapper); + + interface ItemMapper { + + int mapItem(int item); + + default boolean canFixItem(int item) { + return this.mapItem(item) >= 0; + } + + default boolean canFixItem(ItemStack item) { + return this.mapItem(item.id) >= 0; + } + + default void fixItem(ItemStack item) { + item.id = this.mapItem(item.id); + } + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/ItemIdFixer.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/ItemIdFixer.java new file mode 100644 index 000000000..dbc83f781 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/ItemIdFixer.java @@ -0,0 +1,19 @@ +package net.ornithemc.osl.items.impl.item; + +import net.minecraft.item.Item; + +import net.ornithemc.osl.registries.api.registry.sync.IdFixer; + +public class ItemIdFixer implements IdFixer { + + @Override + public void apply() { + for (int id = 0; id < Item.BY_ID.length; id++) { + Item item = Item.BY_ID[id]; + + if (item != null) { + item.id = id; + } + } + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/ItemStatsMapper.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/ItemStatsMapper.java new file mode 100644 index 000000000..5d57521f4 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/ItemStatsMapper.java @@ -0,0 +1,73 @@ +package net.ornithemc.osl.items.impl.item; + +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Set; + +import it.unimi.dsi.fastutil.ints.Int2IntFunction; + +import net.minecraft.stat.ItemStat; +import net.minecraft.stat.Stat; + +import net.ornithemc.osl.items.impl.mixin.common.ItemStatAccess; +import net.ornithemc.osl.registries.api.registry.sync.IdMapper; +import net.ornithemc.osl.registries.api.registry.sync.RegistryMappings; + +public class ItemStatsMapper implements IdMapper { + + public static ItemStatsMapper of(List stats) { + return new ItemStatsMapper(stats); + } + + private final List stats; + private final Set missing; + + private boolean applied; + + private ItemStatsMapper(List stats) { + this.stats = stats; + this.missing = Collections.newSetFromMap(new IdentityHashMap<>()); + } + + @Override + public void apply(RegistryMappings mappings) { + this.missing.clear(); + this.fixItemStats(mappings::remap, true); + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + this.fixItemStats(mappings::unmap, false); + this.missing.clear(); + } + + this.applied = false; + } + + private void fixItemStats(Int2IntFunction mapper, boolean storeMissing) { + for (Stat stat : this.stats) { + if (!(stat instanceof ItemStat)) { + continue; + } + + ItemStatAccess itemStat = (ItemStatAccess) stat; + + if (this.missing.contains(stat)) { + continue; + } + + int oldId = itemStat.accessItem(); + int newId = mapper.applyAsInt(oldId); + + if (newId >= 0) { + itemStat.setItem(newId); + } else if (storeMissing) { + this.missing.add(stat); + } + } + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/ItemUtil.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/ItemUtil.java new file mode 100644 index 000000000..285ce6088 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/ItemUtil.java @@ -0,0 +1,27 @@ +package net.ornithemc.osl.items.impl.item; + +import net.minecraft.block.Block; +import net.minecraft.item.BlockItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +import net.ornithemc.osl.items.api.ItemRegistry; +import net.ornithemc.osl.items.impl.mixin.common.BlockItemAccess; + +public final class ItemUtil { + + public static boolean blockItemsInitialized; + + public static int blockId(ItemStack item) { + return item.getItem() instanceof BlockItem ? ((BlockItemAccess) item.getItem()).accessBlock() : 0; + } + + public static int itemId(int block) { + return itemId(Block.BY_ID[block]); + } + + public static int itemId(Block block) { + Item item = ItemRegistry.getItem(block); + return item == null ? 0 : item.id; + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/LootTableMapper.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/LootTableMapper.java new file mode 100644 index 000000000..848849926 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/LootTableMapper.java @@ -0,0 +1,82 @@ +package net.ornithemc.osl.items.impl.item; + +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Set; + +import it.unimi.dsi.fastutil.ints.Int2IntFunction; + +import net.minecraft.item.ItemStack; +import net.minecraft.world.gen.structure.LootEntry; + +import net.ornithemc.osl.items.impl.ItemsMixinPlugin; +import net.ornithemc.osl.items.impl.LootEntryAccess; +import net.ornithemc.osl.registries.api.registry.sync.IdMapper; +import net.ornithemc.osl.registries.api.registry.sync.RegistryMappings; + +public class LootTableMapper implements IdMapper { + + public static LootTableMapper of(LootEntry... lootTable) { + return new LootTableMapper(lootTable); + } + + private final LootEntry[] lootTable; + private final Set missing; + + private boolean applied; + + private LootTableMapper(LootEntry[] lootTable) { + this.lootTable = lootTable; + this.missing = Collections.newSetFromMap(new IdentityHashMap<>()); + } + + @Override + public void apply(RegistryMappings mappings) { + this.missing.clear(); + this.fixLootItems(mappings::remap, true); + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + this.fixLootItems(mappings::unmap, false); + this.missing.clear(); + } + + this.applied = false; + } + + private void fixLootItems(Int2IntFunction mapper, boolean storeMissing) { + for (LootEntry loot : this.lootTable) { + if (this.missing.contains(loot)) { + continue; + } + + LootEntryAccess lootAccess = (LootEntryAccess) loot; + + if (ItemsMixinPlugin.LOOT_ENTRY_USES_ITEM_STACK) { + ItemStack item = lootAccess.osl$items$getItemStack(); + + int oldId = item.id; + int newId = mapper.applyAsInt(oldId); + + if (newId >= 0) { + item.id = newId; + } else if (storeMissing) { + this.missing.add(loot); + } + } else { + int oldId = lootAccess.osl$items$getItem(); + int newId = mapper.applyAsInt(oldId); + + if (newId >= 0) { + lootAccess.osl$items$setItem(newId); + } else if (storeMissing) { + this.missing.add(loot); + } + } + } + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/SmeltingRecipesMapper.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/SmeltingRecipesMapper.java new file mode 100644 index 000000000..c2ada275d --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/item/SmeltingRecipesMapper.java @@ -0,0 +1,80 @@ +package net.ornithemc.osl.items.impl.item; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import it.unimi.dsi.fastutil.ints.Int2IntFunction; + +import net.minecraft.item.ItemStack; + +import net.ornithemc.osl.registries.api.registry.sync.IdMapper; +import net.ornithemc.osl.registries.api.registry.sync.IntegerMapMapper; +import net.ornithemc.osl.registries.api.registry.sync.RegistryMappings; + +public class SmeltingRecipesMapper implements IdMapper { + + public static SmeltingRecipesMapper of(Map recipes) { + return new SmeltingRecipesMapper(recipes); + } + + private final IntegerMapMapper registryMapper; + + private final Map recipes; + private final Map missing; + + private boolean applied; + + private SmeltingRecipesMapper(Map recipes) { + this.registryMapper = IntegerMapMapper.of(recipes); + + this.recipes = recipes; + this.missing = new HashMap<>(); + } + + @Override + public void apply(RegistryMappings mappings) { + this.missing.clear(); + this.fixRecipes(mappings::remap, true); + + this.registryMapper.apply(mappings); + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + this.registryMapper.undo(mappings); + + if (this.applied) { + this.fixRecipes(mappings::unmap, false); + this.recipes.putAll(this.missing); + } + + this.applied = false; + } + + private void fixRecipes(Int2IntFunction mapper, boolean storeMissing) { + Iterator> it = this.recipes.entrySet().iterator(); + + while (it.hasNext()) { + Map.Entry recipe = it.next(); + + int ingredient = recipe.getKey(); + ItemStack result = recipe.getValue(); + + int oldId = result.id; + int newId = mapper.applyAsInt(oldId); + + if (newId >= 0) { + result.id = newId; + } else { + it.remove(); + + if (storeMissing) { + this.missing.put(ingredient, result); + } + } + } + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/BlockMixin_PickItem.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/BlockMixin_PickItem.java new file mode 100644 index 000000000..71c6e3bf3 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/BlockMixin_PickItem.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; + +import net.minecraft.block.Block; + +import net.ornithemc.osl.items.impl.item.ItemUtil; + +@Mixin(Block.class) +public class BlockMixin_PickItem { + + @WrapOperation( + method = "getPickItem", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/Block;id:I" + ) + ) + private int osl$items$fixBlockItem(Block block, Operation op) { + return ItemUtil.itemId(block); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/CustomizeFlatWorldScreen_LayerListWidgetMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/CustomizeFlatWorldScreen_LayerListWidgetMixin.java new file mode 100644 index 000000000..2eaf9ce0f --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/CustomizeFlatWorldScreen_LayerListWidgetMixin.java @@ -0,0 +1,27 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; + +import net.minecraft.item.Item; +import net.minecraft.world.gen.chunk.FlatWorldLayer; + +import net.ornithemc.osl.items.impl.item.ItemUtil; + +@Mixin(targets = "net/minecraft/client/gui/screen/CustomizeFlatWorldScreen$LayerListWidget") +public class CustomizeFlatWorldScreen_LayerListWidgetMixin { + + @WrapOperation( + method = "renderEntry", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/gen/chunk/FlatWorldLayer;getBlock()I" + ) + ) + private int osl$items$fixBlockItem(FlatWorldLayer layer, Operation op) { + return ItemUtil.itemId(layer.getBlock()); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemInHandRendererMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemInHandRendererMixin.java new file mode 100644 index 000000000..056181d8e --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemInHandRendererMixin.java @@ -0,0 +1,36 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.block.Block; +import net.minecraft.client.render.ItemInHandRenderer; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemStack; + +import net.ornithemc.osl.items.impl.mixin.common.BlockItemAccess; + +@Mixin(ItemInHandRenderer.class) +public class ItemInHandRendererMixin { + + @Definition( + id = "BY_ID", + field = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;" + ) + @Expression("BY_ID[?]") + @WrapOperation( + method = "render", + at = @At( + value = "MIXINEXTRAS:EXPRESSION" + ) + ) + private Block osl$items$fixBlockCheck(Block[] BY_ID, int id, Operation op, @Local ItemStack item) { + return item.getItem() instanceof BlockItem ? op.call(BY_ID, ((BlockItemAccess) item.getItem()).accessBlock()) : null; + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin.java new file mode 100644 index 000000000..85715cac6 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin.java @@ -0,0 +1,36 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.block.Block; +import net.minecraft.client.render.entity.ItemRenderer; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemStack; + +import net.ornithemc.osl.items.impl.mixin.common.BlockItemAccess; + +@Mixin(ItemRenderer.class) +public class ItemRendererMixin { + + @Definition( + id = "BY_ID", + field = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;" + ) + @Expression("BY_ID[?]") + @WrapOperation( + method = "render", + at = @At( + value = "MIXINEXTRAS:EXPRESSION" + ) + ) + private Block osl$items$fixBlockCheck(Block[] BY_ID, int id, Operation op, @Local ItemStack item) { + return item.getItem() instanceof BlockItem ? op.call(BY_ID, ((BlockItemAccess) item.getItem()).accessBlock()) : null; + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin_12w50a.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin_12w50a.java new file mode 100644 index 000000000..9141095f5 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin_12w50a.java @@ -0,0 +1,36 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.block.Block; +import net.minecraft.client.render.entity.ItemRenderer; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemStack; + +import net.ornithemc.osl.items.impl.mixin.common.BlockItemAccess; + +@Mixin(ItemRenderer.class) +public class ItemRendererMixin_12w50a { + + @Definition( + id = "BY_ID", + field = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;" + ) + @Expression("BY_ID[?]") + @WrapOperation( + method = "m_29207578", + at = @At( + value = "MIXINEXTRAS:EXPRESSION" + ) + ) + private Block osl$items$fixBlockCheck(Block[] BY_ID, int id, Operation op, @Local ItemStack item) { + return item.getItem() instanceof BlockItem ? op.call(BY_ID, ((BlockItemAccess) item.getItem()).accessBlock()) : null; + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin_13w02a.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin_13w02a.java new file mode 100644 index 000000000..cbbc81d97 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin_13w02a.java @@ -0,0 +1,36 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.block.Block; +import net.minecraft.client.render.entity.ItemRenderer; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemStack; + +import net.ornithemc.osl.items.impl.mixin.common.BlockItemAccess; + +@Mixin(ItemRenderer.class) +public class ItemRendererMixin_13w02a { + + @Definition( + id = "BY_ID", + field = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;" + ) + @Expression("BY_ID[?]") + @WrapOperation( + method = "renderGuiItem", + at = @At( + value = "MIXINEXTRAS:EXPRESSION" + ) + ) + private Block osl$items$fixBlockCheck(Block[] BY_ID, int id, Operation op, @Local ItemStack item) { + return item.getItem() instanceof BlockItem ? op.call(BY_ID, ((BlockItemAccess) item.getItem()).accessBlock()) : null; + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin_1_6.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin_1_6.java new file mode 100644 index 000000000..67b894d25 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin_1_6.java @@ -0,0 +1,34 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.block.Block; +import net.minecraft.client.render.entity.ItemRenderer; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemStack; + +@Mixin(ItemRenderer.class) +public class ItemRendererMixin_1_6 { + + @Definition( + id = "BY_ID", + field = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;" + ) + @Expression("BY_ID.length") + @WrapOperation( + method = "render", + at = @At( + value = "MIXINEXTRAS:EXPRESSION" + ) + ) + private int osl$items$fixBlockIdCheck(Block[] BY_ID, Operation op, @Local ItemStack item) { + return item.getItem() instanceof BlockItem ? op.call((Object) BY_ID) : 0; + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin_b1_4_01_12w34a_13w01a.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin_b1_4_01_12w34a_13w01a.java new file mode 100644 index 000000000..4c0e0e3c8 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin_b1_4_01_12w34a_13w01a.java @@ -0,0 +1,48 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.block.Block; +import net.minecraft.client.render.entity.ItemRenderer; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemStack; + +import net.ornithemc.osl.items.impl.mixin.common.BlockItemAccess; + +@Mixin(ItemRenderer.class) +public class ItemRendererMixin_b1_4_01_12w34a_13w01a { + + @ModifyExpressionValue( + method = "renderGuiItem", + at = @At( + value = "CONSTANT", + args = "intValue=256" + ) + ) + private int osl$items$fixBlockIdCheck(int maxBlockId, @Local ItemStack item) { + return item.getItem() instanceof BlockItem ? item.id + 1 : 0; + } + + @Definition( + id = "BY_ID", + field = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;" + ) + @Expression("BY_ID[?]") + @WrapOperation( + method = "renderGuiItem", + at = @At( + value = "MIXINEXTRAS:EXPRESSION" + ) + ) + private Block osl$items$fixBlockCheck(Block[] BY_ID, int id, Operation op, @Local ItemStack item) { + return item.getItem() instanceof BlockItem ? op.call(BY_ID, ((BlockItemAccess) item.getItem()).accessBlock()) : null; + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin_b1_5_12w32a.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin_b1_5_12w32a.java new file mode 100644 index 000000000..b75f5614e --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/ItemRendererMixin_b1_5_12w32a.java @@ -0,0 +1,48 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.block.Block; +import net.minecraft.client.render.entity.ItemRenderer; +import net.minecraft.item.BlockItem; +import net.minecraft.item.Item; + +import net.ornithemc.osl.items.impl.mixin.common.BlockItemAccess; + +@Mixin(ItemRenderer.class) +public class ItemRendererMixin_b1_5_12w32a { + + @ModifyExpressionValue( + method = "renderGuiItem", + at = @At( + value = "CONSTANT", + args = "intValue=256" + ) + ) + private int osl$items$fixBlockIdCheck(int maxBlockId, @Local(ordinal = 0) int item) { + return Item.BY_ID[item] instanceof BlockItem ? item + 1 : 0; + } + + @Definition( + id = "BY_ID", + field = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;" + ) + @Expression("BY_ID[?]") + @WrapOperation( + method = "renderGuiItem", + at = @At( + value = "MIXINEXTRAS:EXPRESSION" + ) + ) + private Block osl$items$fixBlockCheck(Block[] BY_ID, int id, Operation op, @Local(ordinal = 0) int item) { + return Item.BY_ID[item] instanceof BlockItem ? op.call(BY_ID, ((BlockItemAccess) Item.BY_ID[item]).accessBlock()) : null; + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/MinecraftMixinMid.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/MinecraftMixinMid.java new file mode 100644 index 000000000..4bab31894 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/MinecraftMixinMid.java @@ -0,0 +1,65 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; + +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalIntRef; + +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.item.Item; + +import net.ornithemc.osl.items.api.ItemRegistry; + +@Mixin(Minecraft.class) +public class MinecraftMixinMid { + + @ModifyVariable( + method = "doPick", + index = 2, + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/World;getBlock(III)I", + shift = Shift.BY, + by = 2 // after local store + ) + ) + private int osl$items$fixBlockItemId(int id, @Share("osl$items$blockId") LocalIntRef blockId) { + blockId.set(id); + + Block block = Block.BY_ID[id]; + if (block == null) { + return 0; + } + + Item item = ItemRegistry.getItem(block); + if (item == null) { + return 0; + } + + return item.id; + } + + @Definition( + id = "BY_ID", + field = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;" + ) + @Expression("BY_ID[?]") + @WrapOperation( + method = "doPick", + at = @At( + value = "MIXINEXTRAS:EXPRESSION" + ) + ) + private Block osl$items$fixBlockCheck1(Block[] BY_ID, int id, Operation op, @Share("osl$items$blockId") LocalIntRef blockId) { + return op.call(BY_ID, blockId.get()); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/MinecraftMixinNew.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/MinecraftMixinNew.java new file mode 100644 index 000000000..8353ea4d7 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/MinecraftMixinNew.java @@ -0,0 +1,29 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +import net.minecraft.client.Minecraft; +import net.minecraft.item.BlockItem; +import net.minecraft.item.Item; + +import net.ornithemc.osl.items.impl.mixin.common.BlockItemAccess; + +@Mixin(Minecraft.class) +public class MinecraftMixinNew { + + @ModifyVariable( + method = "doPick", + index = 2, + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/item/Item;hasCustomData()Z", + shift = Shift.AFTER + ) + ) + private int osl$items$fixBlockId(int item) { + return Item.BY_ID[item] instanceof BlockItem ? ((BlockItemAccess) Item.BY_ID[item]).accessBlock() : 0; + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/MinecraftMixinOld.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/MinecraftMixinOld.java new file mode 100644 index 000000000..64daa583f --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/MinecraftMixinOld.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.item.Item; + +import net.ornithemc.osl.items.api.ItemRegistry; + +@Mixin(Minecraft.class) +public class MinecraftMixinOld { + + @ModifyVariable( + method = "doPick", + index = 1, + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/World;getBlock(III)I", + shift = Shift.BY, + by = 2 // after local store + ) + ) + private int osl$items$fixBlockItemId(int id) { + Block block = Block.BY_ID[id]; + if (block == null) { + return 0; + } + + Item item = ItemRegistry.getItem(block); + if (item == null) { + return 0; + } + + return item.id; + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/PlayerRendererMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/PlayerRendererMixin.java new file mode 100644 index 000000000..06c31166d --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/PlayerRendererMixin.java @@ -0,0 +1,48 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.block.Block; +import net.minecraft.client.render.entity.PlayerRenderer; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemStack; + +import net.ornithemc.osl.items.impl.mixin.common.BlockItemAccess; + +@Mixin(PlayerRenderer.class) +public class PlayerRendererMixin { + + @ModifyExpressionValue( + method = "renderMore", + at = @At( + value = "CONSTANT", + args = "intValue=256" + ) + ) + private int osl$items$fixBlockIdCheck(int maxBlockId, @Local ItemStack item) { + return item.getItem() instanceof BlockItem ? item.id + 1 : 0; + } + + @Definition( + id = "BY_ID", + field = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;" + ) + @Expression("BY_ID[?]") + @WrapOperation( + method = "renderMore", + at = @At( + value = "MIXINEXTRAS:EXPRESSION" + ) + ) + private Block osl$items$fixBlockCheck(Block[] BY_ID, int id, Operation op, @Local ItemStack item) { + return item.getItem() instanceof BlockItem ? op.call(BY_ID, ((BlockItemAccess) item.getItem()).accessBlock()) : null; + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/PlayerRendererMixinNew.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/PlayerRendererMixinNew.java new file mode 100644 index 000000000..7d2a9dbee --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/PlayerRendererMixinNew.java @@ -0,0 +1,50 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.block.Block; +import net.minecraft.client.render.entity.PlayerRenderer; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemStack; + +import net.ornithemc.osl.items.impl.mixin.common.BlockItemAccess; + +@Mixin(PlayerRenderer.class) +public class PlayerRendererMixinNew { + + @ModifyExpressionValue( + method = "renderMore", + at = @At( + value = "CONSTANT", + args = "intValue=256", + ordinal = 1 + ) + ) + private int osl$items$fixBlockIdCheck(int maxBlockId, @Local(ordinal = 1) ItemStack item) { + return item.getItem() instanceof BlockItem ? item.id + 1 : 0; + } + + @Definition( + id = "BY_ID", + field = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;" + ) + @Expression("BY_ID[?]") + @WrapOperation( + method = "renderMore", + at = @At( + value = "MIXINEXTRAS:EXPRESSION", + ordinal = 1 + ) + ) + private Block osl$items$fixBlockCheck(Block[] BY_ID, int id, Operation op, @Local(ordinal = 1) ItemStack item) { + return item.getItem() instanceof BlockItem ? op.call(BY_ID, ((BlockItemAccess) item.getItem()).accessBlock()) : null; + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/SlabBlockMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/SlabBlockMixin.java new file mode 100644 index 000000000..d98c57bd9 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/SlabBlockMixin.java @@ -0,0 +1,27 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; + +import net.minecraft.block.SlabBlock; + +import net.ornithemc.osl.items.impl.item.ItemUtil; + +@Mixin(SlabBlock.class) +public class SlabBlockMixin { + + @WrapOperation( + method = "getPickItem", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/SlabBlock;id:I", + ordinal= 1 + ) + ) + private int osl$items$fixBlockItem(SlabBlock block, Operation op) { + return ItemUtil.itemId(block); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/WitchRendererMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/WitchRendererMixin.java new file mode 100644 index 000000000..2c8c8f232 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/client/WitchRendererMixin.java @@ -0,0 +1,48 @@ +package net.ornithemc.osl.items.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.block.Block; +import net.minecraft.client.render.entity.WitchRenderer; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemStack; + +import net.ornithemc.osl.items.impl.mixin.common.BlockItemAccess; + +@Mixin(WitchRenderer.class) +public class WitchRendererMixin { + + @ModifyExpressionValue( + method = "renderMore", + at = @At( + value = "CONSTANT", + args = "intValue=256" + ) + ) + private int osl$items$fixBlockIdCheck(int maxBlockId, @Local ItemStack item) { + return item.getItem() instanceof BlockItem ? item.id + 1 : 0; + } + + @Definition( + id = "BY_ID", + field = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;" + ) + @Expression("BY_ID[?]") + @WrapOperation( + method = "renderMore", + at = @At( + value = "MIXINEXTRAS:EXPRESSION" + ) + ) + private Block osl$items$fixBlockCheck(Block[] BY_ID, int id, Operation op, @Local ItemStack item) { + return item.getItem() instanceof BlockItem ? op.call(BY_ID, ((BlockItemAccess) item.getItem()).accessBlock()) : null; + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/AchievementsMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/AchievementsMixin.java new file mode 100644 index 000000000..66e29fb98 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/AchievementsMixin.java @@ -0,0 +1,34 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import java.util.List; + +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.stat.achievement.AchievementStat; +import net.minecraft.stat.achievement.Achievements; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.items.impl.item.AchievementsIconMapper; +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.api.registry.SyncedRegistries; + +@Mixin(Achievements.class) +public class AchievementsMixin { + + @Shadow + private static List ALL; + + @Inject( + method = "init", + at = @At( + value = "TAIL" + ) + ) + private static void osl$items$registerAchievementsIconMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("achievements/icon"), AchievementsIconMapper.of(ALL)); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/AxisBlockMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/AxisBlockMixin.java new file mode 100644 index 000000000..ea24adaff --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/AxisBlockMixin.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; + +import net.minecraft.block.AxisBlock; + +import net.ornithemc.osl.items.impl.item.ItemUtil; + +@Mixin(AxisBlock.class) +public class AxisBlockMixin { + + @WrapOperation( + method = "getSilkTouchDrop", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/AxisBlock;id:I" + ) + ) + private int osl$items$fixBlockItem(AxisBlock block, Operation op) { + return ItemUtil.itemId(block); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockItemAccess.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockItemAccess.java index 4d2224a94..282b3aab6 100644 --- a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockItemAccess.java +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockItemAccess.java @@ -11,4 +11,7 @@ public interface BlockItemAccess { @Accessor("block") int accessBlock(); + @Accessor("block") + void setBlock(int block); + } diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixin.java index 61efe4bde..f554c0978 100644 --- a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixin.java +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixin.java @@ -5,22 +5,26 @@ 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.Slice; +import org.spongepowered.asm.mixin.injection.At.Shift; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import com.llamalad7.mixinextras.sugar.Share; -import com.llamalad7.mixinextras.sugar.ref.LocalBooleanRef; -import com.llamalad7.mixinextras.sugar.ref.LocalRef; import net.minecraft.block.Block; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; +import net.ornithemc.osl.blocks.impl.VanillaBlocks; import net.ornithemc.osl.items.impl.ItemRegistryImpl; +import net.ornithemc.osl.items.impl.VanillaItems; -@Mixin(Block.class) +@Mixin( + value = Block.class, + priority = 1001 // make sure blocks mixin is applied first +) public class BlockMixin { /* @@ -51,35 +55,26 @@ public class BlockMixin { * that block item stats initialize correctly, but *before* Vanilla * block items are initialized. This is because Vanilla auto-generates * most block items, but we want to allow mods to register special - * item forms of their blocks. + * item forms for their blocks. */ @Inject( method = "", - slice = @Slice( - from = @At( - value = "FIELD", - opcode = Opcodes.PUTSTATIC, - target = "Lnet/minecraft/block/Block;STONE:Lnet/minecraft/block/Block;" - ) - ), at = @At( - value = "FIELD", - target = "Lnet/minecraft/item/Item;BY_ID:[Lnet/minecraft/item/Item;", - ordinal = 0 + // inject before the for-loop for auto block item generation + value = "JUMP", + opcode = Opcodes.IF_ICMPGE, + shift = Shift.BY, + // it's extreme but this ensures that the injector is only invoked once + by = -5 ) ) - private static void osl$items$registerBlockItems(CallbackInfo ci, @Share("osl$items$blockItemsRegistered") LocalBooleanRef blockItemsRegistered) { - // in some versions this injector targets a for-loop - if (!blockItemsRegistered.get()) { - // Item registration would be initiated here anyway - // force it to happen *before* we register block items - Item.BY_ID.getClass(); + private static void osl$items$registerBlockItems(CallbackInfo ci) { + // trigger Item class init in Beta 1.1 and below + // it would otherwise be triggered in the for-loop anyway + Item.BY_ID.getClass(); - ItemRegistryImpl.registerBlocks(); - } - - blockItemsRegistered.set(true); + ItemRegistryImpl.registerBlockItems(); } @WrapOperation( @@ -90,28 +85,32 @@ public class BlockMixin { ) ) private static BlockItem osl$items$cancelAutoGeneratedBlockItem(int id, Operation op) { - if (ItemRegistryImpl.BLOCK_ITEMS.containsKey(Block.BY_ID[id + 256])) { + Block block = Block.BY_ID[id + VanillaItems.ITEM_ID_OFFSET]; + + if (block.isAir() || ItemRegistryImpl.BLOCK_ITEMS.containsKey(block)) { return null; } else { + // for Vanilla block items, ensure block ID == item ID + // for custom mod items, let Items API assign a new ID + if (block.id > VanillaBlocks.MAX_ID) { + id = Item.AUTO_ASSIGN_ID; + } + return op.call(id); } } + @Definition( + id = "BY_ID", + field = "Lnet/minecraft/item/Item;BY_ID:[Lnet/minecraft/item/Item;" + ) + @Expression("BY_ID[?] = ?") @WrapOperation( method = "", at = @At( - value = "FIELD", - target = "Lnet/minecraft/item/Item;BY_ID:[Lnet/minecraft/item/Item;", - opcode = Opcodes.GETSTATIC, - args = "array=set" + value = "MIXINEXTRAS:EXPRESSION" ) ) - private static Item[] osl$items$cancelPutBlockItemInArray(Operation op, @Share("osl$items$dummyItemArray") LocalRef dummyItems) { - // operation is unnecessary as Item:: already puts the item in the array - if (dummyItems.get() == null) { - dummyItems.set(new Item[Item.BY_ID.length]); - } - - return dummyItems.get(); + private static void osl$items$cancelPutBlockItemInArray(Item[] BY_ID, int id, Item item, Operation op) { } } diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixinNew.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixinNew.java index 4b83fda4f..d419688ad 100644 --- a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixinNew.java +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixinNew.java @@ -19,7 +19,7 @@ public class BlockMixinNew { target = "Lnet/minecraft/stat/Stats;initBlockStats()V" ) ) - private static void osl$items$initBlockItems(CallbackInfo ci) { - ItemRegistryImpl.initBlocks(); + private static void osl$items$registerVanillaBlockItems(CallbackInfo ci) { + ItemRegistryImpl.registerVanillaBlockItems(); } } diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixinOld.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixinOld.java index bcd2f4902..d4228dbdc 100644 --- a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixinOld.java +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixinOld.java @@ -18,7 +18,7 @@ public class BlockMixinOld { value = "TAIL" ) ) - private static void osl$items$initBlockItems(CallbackInfo ci) { - ItemRegistryImpl.initBlocks(); + private static void osl$items$registerVanillaBlockItems(CallbackInfo ci) { + ItemRegistryImpl.registerVanillaBlockItems(); } } diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixin_DropItem.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixin_DropItem.java new file mode 100644 index 000000000..2da8f034f --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixin_DropItem.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; + +import net.minecraft.block.Block; + +import net.ornithemc.osl.items.impl.item.ItemUtil; + +@Mixin(Block.class) +public class BlockMixin_DropItem { + + @WrapOperation( + method = "getDropItem", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/Block;id:I" + ) + ) + private int osl$items$fixBlockItem(Block block, Operation op) { + return ItemUtil.itemId(block); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixin_SilkTouchDropItem.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixin_SilkTouchDropItem.java new file mode 100644 index 000000000..80270e0b4 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/BlockMixin_SilkTouchDropItem.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; + +import net.minecraft.block.Block; + +import net.ornithemc.osl.items.impl.item.ItemUtil; + +@Mixin(Block.class) +public class BlockMixin_SilkTouchDropItem { + + @WrapOperation( + method = "getSilkTouchDrop", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/Block;id:I" + ) + ) + private int osl$items$fixBlockItem(Block block, Operation op) { + return ItemUtil.itemId(block); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/CraftingManagerMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/CraftingManagerMixin.java new file mode 100644 index 000000000..51973b865 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/CraftingManagerMixin.java @@ -0,0 +1,52 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import java.util.Comparator; +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +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.crafting.CraftingManager; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.items.impl.item.CraftingRecipesMapper; +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.api.registry.SyncedRegistries; + +@Mixin(CraftingManager.class) +public class CraftingManagerMixin { + + @Shadow + private List recipes; + + @Unique + private Comparator sorter; + + @WrapOperation( + method = "", + at = @At( + value = "INVOKE", + target = "Ljava/util/Collections;sort(Ljava/util/List;Ljava/util/Comparator;)V" + ) + ) + private void osl$items$captureSorter(List recipes, Comparator sorter, Operation op) { + op.call(recipes, this.sorter = sorter); + } + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$registerRecipesMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("crafting/recipe"), CraftingRecipesMapper.of(this.recipes, this.sorter)); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/FurnaceBlockEntityMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/FurnaceBlockEntityMixin.java new file mode 100644 index 000000000..bee889196 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/FurnaceBlockEntityMixin.java @@ -0,0 +1,46 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.block.Block; +import net.minecraft.block.entity.FurnaceBlockEntity; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemStack; + +@Mixin(FurnaceBlockEntity.class) +public class FurnaceBlockEntityMixin { + + @ModifyExpressionValue( + method = "getFuelTime", + at = @At( + value = "CONSTANT", + args = "intValue=256" + ) + ) + private static int osl$items$fixBlockIdCheck(int maxBlockId, @Local ItemStack item) { + return item.getItem() instanceof BlockItem ? item.id + 1 : 0; + } + + @Definition( + id = "BY_ID", + field = "Lnet/minecraft/block/Block;BY_ID:[Lnet/minecraft/block/Block;" + ) + @Expression("BY_ID[?]") + @WrapOperation( + method = "getFuelTime", + at = @At( + value = "MIXINEXTRAS:EXPRESSION" + ) + ) + private static Block osl$items$fixBlockCheck(Block[] BY_ID, int id, Operation op, @Local ItemStack item) { + return item.getItem() instanceof BlockItem ? op.call(BY_ID, ((BlockItemAccess) item.getItem()).accessBlock()) : null; + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/FurnaceBlockEntityMixinNew.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/FurnaceBlockEntityMixinNew.java new file mode 100644 index 000000000..5c4a55b77 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/FurnaceBlockEntityMixinNew.java @@ -0,0 +1,27 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; + +import net.minecraft.block.Block; +import net.minecraft.block.entity.FurnaceBlockEntity; + +import net.ornithemc.osl.items.impl.item.ItemUtil; + +@Mixin(FurnaceBlockEntity.class) +public class FurnaceBlockEntityMixinNew { + + @WrapOperation( + method = "getFuelTime", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/Block;id:I" + ) + ) + private static int osl$items$fixBlockItem(Block block, Operation op) { + return ItemUtil.itemId(block); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/FurnaceBlockEntityMixinOld.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/FurnaceBlockEntityMixinOld.java new file mode 100644 index 000000000..0251034b3 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/FurnaceBlockEntityMixinOld.java @@ -0,0 +1,27 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; + +import net.minecraft.block.Block; +import net.minecraft.block.entity.FurnaceBlockEntity; + +import net.ornithemc.osl.items.impl.item.ItemUtil; + +@Mixin(FurnaceBlockEntity.class) +public class FurnaceBlockEntityMixinOld { + + @WrapOperation( + method = "m_37310100", // getResult + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/Block;id:I" + ) + ) + private int osl$items$fixBlockItem(Block block, Operation op) { + return ItemUtil.itemId(block); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/GravelBlockMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/GravelBlockMixin.java new file mode 100644 index 000000000..eea26041d --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/GravelBlockMixin.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; + +import net.minecraft.block.GravelBlock; + +import net.ornithemc.osl.items.impl.item.ItemUtil; + +@Mixin(GravelBlock.class) +public class GravelBlockMixin { + + @WrapOperation( + method = "getDropItem", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/GravelBlock;id:I" + ) + ) + private int osl$items$fixBlockItem(GravelBlock block, Operation op) { + return ItemUtil.itemId(block); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java new file mode 100644 index 000000000..689f26af7 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin.java @@ -0,0 +1,133 @@ +package net.ornithemc.osl.items.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.entity.living.mob.passive.VillagerEntity; +import net.minecraft.item.Item; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.gen.feature.DungeonFeature; +import net.minecraft.world.gen.structure.FortressPieces; +import net.minecraft.world.gen.structure.MineshaftPieces; +import net.minecraft.world.gen.structure.StrongholdPieces.ChestCorridor; +import net.minecraft.world.gen.structure.StrongholdPieces.Library; +import net.minecraft.world.gen.structure.StrongholdPieces.RoomCrossing; +import net.minecraft.world.gen.structure.TemplePieces.DesertPyramid; +import net.minecraft.world.gen.structure.TemplePieces.JungleTemple; +import net.minecraft.world.gen.structure.VillagePieces.BlacksmithHouse; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.core.impl.util.MinecraftVersion; +import net.ornithemc.osl.items.api.item.ItemExtension; +import net.ornithemc.osl.items.impl.VanillaBlockItems; +import net.ornithemc.osl.items.impl.VanillaItems; +import net.ornithemc.osl.items.impl.item.LootTableMapper; +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.api.registry.SyncedRegistries; +import net.ornithemc.osl.registries.api.registry.sync.DynamicArrays; +import net.ornithemc.osl.registries.api.registry.sync.IntegerMapMapper; +import net.ornithemc.osl.registries.api.registry.sync.ObjectArrayMapper; + +@Mixin(Item.class) +public class ItemMixin implements ItemExtension { + + @Shadow @Final @Mutable + private static Item[] BY_ID; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private static void osl$items$registerArrayMappers(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("item/by_id"), ObjectArrayMapper.of(BY_ID)); + + if (MinecraftVersion.resolve().compareTo("12w21a") >= 0) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("trade/buy_offer"), IntegerMapMapper.of(VillagerEntity.BUY_OFFERS)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("trade/sell_offer"), IntegerMapMapper.of(VillagerEntity.SELL_OFFERS)); + } + if (MinecraftVersion.resolve().compareTo("12w18a") >= 0) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("loot/bonus_chest"), LootTableMapper.of(ServerWorld.BONUS_CHEST_LOOT_ENTRIES)); + } + if (MinecraftVersion.resolve().compareTo("13w18a") >= 0) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("loot/dungeon"), LootTableMapper.of(DungeonFeature.LOOT_ENTRIES)); + } + if (MinecraftVersion.resolve().compareTo("12w01a") >= 0) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("loot/village_blacksmith"), LootTableMapper.of(BlacksmithHouse.LOOT_ENTRIES)); + } + if (MinecraftVersion.resolve().compareTo("b1.9-pre3") >= 0) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("loot/stronghold_corridor_altar"), LootTableMapper.of(ChestCorridor.LOOT_ENTRIES)); + } + if (MinecraftVersion.resolve().compareTo("b1.8-pre1") >= 0) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("loot/stronghold_library"), LootTableMapper.of(Library.LOOT_ENTRIES)); + } + if (MinecraftVersion.resolve().compareTo("b1.9-pre3") >= 0) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("loot/desert_pyramid"), LootTableMapper.of(DesertPyramid.LOOT_ENTRIES)); + } + if (MinecraftVersion.resolve().compareTo("12w22a") >= 0) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("loot/jungle_temple_treasure"), LootTableMapper.of(JungleTemple.TREASURE_LOOT_ENTRIES)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("loot/jungle_temple_trap"), LootTableMapper.of(JungleTemple.TRAP_LOOT_ENTRIES)); + } + if (MinecraftVersion.resolve().compareTo("13w18a") >= 0) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("loot/fortress"), LootTableMapper.of(FortressPieces.FortressPiece.LOOT_ENTRIES)); + } + if (MinecraftVersion.resolve().compareTo("b1.8-pre1") >= 0) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("loot/mineshaft"), LootTableMapper.of(MineshaftPieces.LOOT_ENTRIES)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("loot/stronghold_store_room"), LootTableMapper.of(RoomCrossing.LOOT_ENTRIES)); + } + } + + @ModifyVariable( + method = "", + argsOnly = true, + ordinal = 0, + at = @At( + value = "INVOKE", + target = "Ljava/lang/Object;()V", + shift = Shift.AFTER + ) + ) + private int osl$items$handleAutoAssignId(int id) { + if (id == AUTO_ASSIGN_ID) { + // the Item[] array must contain all items so this should + // give us a valid ID for the Item registry to use. + id = DynamicArrays.length(BY_ID); + + // keep 0-255 free for all Vanilla block items + if (id <= VanillaBlockItems.MAX_ID) { + id = VanillaBlockItems.MAX_ID + 1; + } + + // we offset by -256 because the constructor logic adds 256 + id -= VanillaItems.ITEM_ID_OFFSET; + } + + return id; + } + + @Inject( + method = "", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/item/Item;BY_ID:[Lnet/minecraft/item/Item;", + opcode = Opcodes.GETSTATIC, + args = "array=set" + ) + ) + private void osl$items$growArrays(int id, CallbackInfo ci) { + // the constructor logic adds 256 + int capacity = (id + VanillaItems.ITEM_ID_OFFSET) + 1; + + BY_ID = DynamicArrays.grow(BY_ID, capacity); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixinNew.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixinNew.java index 62f47ab7c..12ca412cc 100644 --- a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixinNew.java +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixinNew.java @@ -32,5 +32,6 @@ public class ItemMixinNew implements ItemExtension { ) private static void osl$items$registerItems(CallbackInfo ci) { ItemRegistryImpl.registerItems(); + ItemRegistryImpl.registerUnknownItems(); } } diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixinOld.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixinOld.java index 498b6344e..04128ea34 100644 --- a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixinOld.java +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixinOld.java @@ -31,5 +31,6 @@ public class ItemMixinOld implements ItemExtension { ) private static void osl$items$registerItems(CallbackInfo ci) { ItemRegistryImpl.registerItems(); + ItemRegistryImpl.registerUnknownItems(); } } diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin_13w02a.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin_13w02a.java new file mode 100644 index 000000000..684032ab7 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin_13w02a.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +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.CallbackInfoReturnable; + +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.impl.util.Util; +import net.ornithemc.osl.items.api.ItemRegistry; + +@Mixin(Item.class) +public class ItemMixin_13w02a { + + @Shadow + private String key; + + @Inject( + method = "getTranslationKey()Ljava/lang/String;", + at = @At( + value = "HEAD" + ) + ) + private void osl$items$autoAssignTranslationKey(CallbackInfoReturnable cir) { + if (this.key == null) { + NamespacedIdentifier identifier = ItemRegistry.getIdentifier((Item) (Object) this); + + if (identifier == null) { + this.key = "unknown"; + } else { + this.key = Util.makeTranslationKey(identifier); + } + } + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin_1_3_1_13w01a.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin_1_3_1_13w01a.java new file mode 100644 index 000000000..d8c72ce76 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin_1_3_1_13w01a.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +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.CallbackInfoReturnable; + +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.impl.util.Util; +import net.ornithemc.osl.items.api.ItemRegistry; + +@Mixin(Item.class) +public class ItemMixin_1_3_1_13w01a { + + @Shadow + private String key; + + @Inject( + method = "getTranslationKey()Ljava/lang/String;", + at = @At( + value = "HEAD" + ) + ) + private void osl$items$autoAssignTranslationKey(CallbackInfoReturnable cir) { + if (this.key == null) { + NamespacedIdentifier identifier = ItemRegistry.getIdentifier((Item) (Object) this); + + if (identifier == null) { + this.key = "item.unknown"; + } else { + this.key = Util.makeTranslationKey("item", identifier); + } + } + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin_b1_0_1_3.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin_b1_0_1_3.java new file mode 100644 index 000000000..bee05537c --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemMixin_b1_0_1_3.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +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.CallbackInfoReturnable; + +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.impl.util.Util; +import net.ornithemc.osl.items.api.ItemRegistry; + +@Mixin(Item.class) +public class ItemMixin_b1_0_1_3 { + + @Shadow + private String key; + + @Inject( + method = "m_27822537", + at = @At( + value = "HEAD" + ) + ) + private void osl$items$autoAssignTranslationKey(CallbackInfoReturnable cir) { + if (this.key == null) { + NamespacedIdentifier identifier = ItemRegistry.getIdentifier((Item) (Object) this); + + if (identifier == null) { + this.key = "item.unknown"; + } else { + this.key = Util.makeTranslationKey("item", identifier); + } + } + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemStackMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemStackMixin.java new file mode 100644 index 000000000..ac900a8b8 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemStackMixin.java @@ -0,0 +1,31 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +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.block.Block; +import net.minecraft.item.ItemStack; + +import net.ornithemc.osl.items.impl.item.ItemUtil; + +@Mixin(ItemStack.class) +public class ItemStackMixin { + + @Shadow + private int id; + + @Inject( + method = "(Lnet/minecraft/block/Block;I)V", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$fixBlockItemId(Block block, int size, CallbackInfo ci) { + if (ItemUtil.blockItemsInitialized) { + this.id = ItemUtil.itemId(block); + } + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemStackMixinNew.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemStackMixinNew.java new file mode 100644 index 000000000..8d84864ef --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemStackMixinNew.java @@ -0,0 +1,31 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +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.block.Block; +import net.minecraft.item.ItemStack; + +import net.ornithemc.osl.items.impl.item.ItemUtil; + +@Mixin(ItemStack.class) +public class ItemStackMixinNew { + + @Shadow + private int id; + + @Inject( + method = "(Lnet/minecraft/block/Block;II)V", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$fixBlockItemId(Block block, int size, int metadata, CallbackInfo ci) { + if (ItemUtil.blockItemsInitialized) { + this.id = ItemUtil.itemId(block); + } + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemStatAccess.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemStatAccess.java new file mode 100644 index 000000000..f3c375752 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ItemStatAccess.java @@ -0,0 +1,19 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.stat.ItemStat; + +@Mixin(ItemStat.class) +public interface ItemStatAccess { + + @Accessor("item") + int accessItem(); + + @Mutable + @Accessor("item") + void setItem(int item); + +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/LeavesBlockMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/LeavesBlockMixin.java new file mode 100644 index 000000000..68c2efae7 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/LeavesBlockMixin.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; + +import net.minecraft.block.LeavesBlock; + +import net.ornithemc.osl.items.impl.item.ItemUtil; + +@Mixin(LeavesBlock.class) +public class LeavesBlockMixin { + + @WrapOperation( + method = "getSilkTouchDrop", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/LeavesBlock;id:I" + ) + ) + private int osl$items$fixBlockItem(LeavesBlock block, Operation op) { + return ItemUtil.itemId(block); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/LootEntryMixinNew.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/LootEntryMixinNew.java new file mode 100644 index 000000000..0dfd2781e --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/LootEntryMixinNew.java @@ -0,0 +1,21 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.item.ItemStack; +import net.minecraft.world.gen.structure.LootEntry; + +import net.ornithemc.osl.items.impl.LootEntryAccess; + +@Mixin(LootEntry.class) +public abstract class LootEntryMixinNew implements LootEntryAccess { + + @Shadow + private ItemStack item; + + @Override + public ItemStack osl$items$getItemStack() { + return this.item; + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/LootEntryMixinOld.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/LootEntryMixinOld.java new file mode 100644 index 000000000..4faafebb1 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/LootEntryMixinOld.java @@ -0,0 +1,25 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.world.gen.structure.LootEntry; + +import net.ornithemc.osl.items.impl.LootEntryAccess; + +@Mixin(LootEntry.class) +public abstract class LootEntryMixinOld implements LootEntryAccess { + + @Shadow + private int f_82867366; // item + + @Override + public int osl$items$getItem() { + return this.f_82867366; + } + + @Override + public void osl$items$setItem(int item) { + this.f_82867366 = item; + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/PaneBlockMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/PaneBlockMixin.java new file mode 100644 index 000000000..f20623903 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/PaneBlockMixin.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; + +import net.minecraft.block.PaneBlock; + +import net.ornithemc.osl.items.impl.item.ItemUtil; + +@Mixin(PaneBlock.class) +public class PaneBlockMixin { + + @WrapOperation( + method = "getSilkTouchDrop", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/PaneBlock;id:I" + ) + ) + private int osl$items$fixBlockItem(PaneBlock block, Operation op) { + return ItemUtil.itemId(block); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/QuartzBlockMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/QuartzBlockMixin.java new file mode 100644 index 000000000..bb00a4051 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/QuartzBlockMixin.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; + +import net.minecraft.block.QuartzBlock; + +import net.ornithemc.osl.items.impl.item.ItemUtil; + +@Mixin(QuartzBlock.class) +public class QuartzBlockMixin { + + @WrapOperation( + method = "getSilkTouchDrop", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/block/QuartzBlock;id:I" + ) + ) + private int osl$items$fixBlockItem(QuartzBlock block, Operation op) { + return ItemUtil.itemId(block); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ShapedRecipeMixinNew.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ShapedRecipeMixinNew.java new file mode 100644 index 000000000..5cd447556 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ShapedRecipeMixinNew.java @@ -0,0 +1,47 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.crafting.recipe.ShapedRecipe; +import net.minecraft.item.ItemStack; + +import net.ornithemc.osl.items.impl.item.FixableRecipe; + +@Mixin(ShapedRecipe.class) +public class ShapedRecipeMixinNew implements FixableRecipe { + + @Shadow + private ItemStack[] ingredients; + @Shadow + private ItemStack result; + @Shadow @Mutable + private int resultItem; + + @Override + public boolean osl$items$canFixRecipe(ItemMapper mapper) { + for (ItemStack ingredient : this.ingredients) { + if (ingredient != null && !mapper.canFixItem(ingredient)) { + return false; + } + } + + return mapper.canFixItem(this.result); + } + + @Override + public void osl$items$fixRecipe(ItemMapper mapper) { + for (ItemStack ingredient : this.ingredients) { + if (ingredient != null) { + mapper.fixItem(ingredient); + } + } + + mapper.fixItem(this.result); + + if (this.resultItem >= 0) { + this.resultItem = mapper.mapItem(this.resultItem); + } + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ShapedRecipeMixinOld.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ShapedRecipeMixinOld.java new file mode 100644 index 000000000..5a2937996 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ShapedRecipeMixinOld.java @@ -0,0 +1,49 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.crafting.recipe.ShapedRecipe; +import net.minecraft.item.ItemStack; + +import net.ornithemc.osl.items.impl.item.FixableRecipe; + +@Mixin(ShapedRecipe.class) +public class ShapedRecipeMixinOld implements FixableRecipe { + + @Shadow + private int[] f_56782558; + @Shadow + private ItemStack result; + @Shadow @Mutable + private int resultItem; + + @Override + public boolean osl$items$canFixRecipe(ItemMapper mapper) { + for (int ingredient : this.f_56782558) { + if (ingredient != -1 && !mapper.canFixItem(ingredient)) { + return false; + } + } + + return mapper.canFixItem(this.result); + } + + @Override + public void osl$items$fixRecipe(ItemMapper mapper) { + for (int i = 0; i < this.f_56782558.length; i++) { + int ingredient = this.f_56782558[i]; + + if (ingredient != -1) { + this.f_56782558[i] = mapper.mapItem(ingredient); + } + } + + mapper.fixItem(this.result); + + if (this.resultItem >= 0) { + this.resultItem = mapper.mapItem(this.resultItem); + } + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ShapelessRecipeMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ShapelessRecipeMixin.java new file mode 100644 index 000000000..b6d4e848b --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/ShapelessRecipeMixin.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.crafting.recipe.ShapelessRecipe; +import net.minecraft.item.ItemStack; + +import net.ornithemc.osl.items.impl.item.FixableRecipe; + +@Mixin(ShapelessRecipe.class) +public class ShapelessRecipeMixin implements FixableRecipe { + + @Shadow + private List ingredients; + @Shadow + private ItemStack result; + + @Override + public boolean osl$items$canFixRecipe(ItemMapper mapper) { + for (ItemStack ingredient : this.ingredients) { + if (!mapper.canFixItem(ingredient)) { + return false; + } + } + + return mapper.canFixItem(this.result); + } + + @Override + public void osl$items$fixRecipe(ItemMapper mapper) { + for (ItemStack ingredient : this.ingredients) { + mapper.fixItem(ingredient); + } + + mapper.fixItem(this.result); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/SmeltingManagerMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/SmeltingManagerMixin.java new file mode 100644 index 000000000..82b4acada --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/SmeltingManagerMixin.java @@ -0,0 +1,34 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import java.util.Map; + +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.crafting.SmeltingManager; +import net.minecraft.item.ItemStack; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.items.impl.item.SmeltingRecipesMapper; +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.api.registry.SyncedRegistries; + +@Mixin(SmeltingManager.class) +public class SmeltingManagerMixin { + + @Shadow + private Map recipes; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$registerRecipesMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("smelting/recipe"), SmeltingRecipesMapper.of(this.recipes)); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/SmeltingManagerMixinNew.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/SmeltingManagerMixinNew.java new file mode 100644 index 000000000..d472e74bf --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/SmeltingManagerMixinNew.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import java.util.Map; + +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.crafting.SmeltingManager; + +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.IntegerMapMapper; + +@Mixin(SmeltingManager.class) +public class SmeltingManagerMixinNew { + + @Shadow + private Map xpResults; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$items$registerRecipesMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("smelting/experience"), IntegerMapMapper.of(this.xpResults)); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/StatsMixin.java b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/StatsMixin.java new file mode 100644 index 000000000..7cbd0c2c4 --- /dev/null +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/items/impl/mixin/common/StatsMixin.java @@ -0,0 +1,46 @@ +package net.ornithemc.osl.items.impl.mixin.common; + +import java.util.List; + +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.stat.Stat; +import net.minecraft.stat.Stats; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.items.impl.item.ItemStatsMapper; +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.api.registry.SyncedRegistries; +import net.ornithemc.osl.registries.api.registry.sync.ObjectArrayMapper; + +@Mixin(Stats.class) +public class StatsMixin { + + @Shadow @Final + private static List ALL; + @Shadow @Final + private static Stat[] ITEMS_CRAFTED; + @Shadow @Final + private static Stat[] ITEMS_USED; + @Shadow @Final + private static Stat[] ITEMS_BROKEN; + + @Inject( + method = "initItemsCraftedStats", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/stat/Stats;mergeBlockStats([Lnet/minecraft/stat/Stat;)V" + ) + ) + private static void osl$items$registerStatsMapper(CallbackInfo ci) { + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("stats/item"), ItemStatsMapper.of(ALL)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("stats/crafted"), ObjectArrayMapper.of(ITEMS_CRAFTED)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("stats/used"), ObjectArrayMapper.of(ITEMS_USED)); + SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("stats/broken"), ObjectArrayMapper.of(ITEMS_BROKEN)); + } +} diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/resources/fabric.mod.json b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/resources/fabric.mod.json index 408f916fb..74925b335 100644 --- a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/resources/fabric.mod.json +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/resources/fabric.mod.json @@ -3,6 +3,11 @@ "id": "osl-items", "version": "0.1.0+mca1.0.1_01-mc1.6.4", "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.items.impl.ItemRegistryImpl::init" + ] + }, "mixins": [ "osl.items.mixins.json" ], @@ -11,6 +16,13 @@ "fabricloader": "\u003e\u003d0.18.0", "minecraft": "\u003e\u003d1.0.0-alpha.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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0", + "osl-registries": "\u003e\u003d0.1.0-", "osl-blocks": "\u003e\u003d0.1.0" }, "name": "OSL Items", diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/resources/osl.items.classtweaker b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/resources/osl.items.classtweaker index d15f78a3c..3bfe4ea64 100644 --- a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/resources/osl.items.classtweaker +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/resources/osl.items.classtweaker @@ -10,4 +10,20 @@ transitive-accessible method net/minecraft/item/Item setPotionIngredient (Ljava/ transitive-accessible method net/minecraft/item/Item setCreativeModeTab (Lnet/minecraft/item/CreativeModeTab;)Lnet/minecraft/item/Item; transitive-accessible method net/minecraft/item/Item setSpriteName (Ljava/lang/String;)Lnet/minecraft/item/Item; -transitive-inject-interface net/minecraft/item/Item net/ornithemc/osl/items/impl/item/ItemExtensionImpl \ No newline at end of file +transitive-inject-interface net/minecraft/item/Item net/ornithemc/osl/items/impl/item/ItemExtensionImpl + +mutable field net/minecraft/item/Item id I +accessible field net/minecraft/entity/living/mob/passive/VillagerEntity BUY_OFFERS Ljava/util/Map; +accessible field net/minecraft/entity/living/mob/passive/VillagerEntity SELL_OFFERS Ljava/util/Map; +accessible field net/minecraft/server/world/ServerWorld BONUS_CHEST_LOOT_ENTRIES [Lnet/minecraft/world/gen/structure/LootEntry; +accessible field net/minecraft/world/gen/feature/DungeonFeature LOOT_ENTRIES [Lnet/minecraft/world/gen/structure/LootEntry; +accessible field net/minecraft/world/gen/structure/VillagePieces$BlacksmithHouse LOOT_ENTRIES [Lnet/minecraft/world/gen/structure/LootEntry; +accessible field net/minecraft/world/gen/structure/StrongholdPieces$ChestCorridor LOOT_ENTRIES [Lnet/minecraft/world/gen/structure/LootEntry; +accessible field net/minecraft/world/gen/structure/StrongholdPieces$Library LOOT_ENTRIES [Lnet/minecraft/world/gen/structure/LootEntry; +accessible field net/minecraft/world/gen/structure/StrongholdPieces$RoomCrossing LOOT_ENTRIES [Lnet/minecraft/world/gen/structure/LootEntry; +accessible field net/minecraft/world/gen/structure/TemplePieces$DesertPyramid LOOT_ENTRIES [Lnet/minecraft/world/gen/structure/LootEntry; +accessible field net/minecraft/world/gen/structure/TemplePieces$JungleTemple TREASURE_LOOT_ENTRIES [Lnet/minecraft/world/gen/structure/LootEntry; +accessible field net/minecraft/world/gen/structure/TemplePieces$JungleTemple TRAP_LOOT_ENTRIES [Lnet/minecraft/world/gen/structure/LootEntry; +accessible class net/minecraft/world/gen/structure/FortressPieces$FortressPiece +accessible field net/minecraft/world/gen/structure/FortressPieces$FortressPiece LOOT_ENTRIES [Lnet/minecraft/world/gen/structure/LootEntry; +accessible field net/minecraft/world/gen/structure/MineshaftPieces LOOT_ENTRIES [Lnet/minecraft/world/gen/structure/LootEntry; diff --git a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/resources/osl.items.mixins.json b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/resources/osl.items.mixins.json index a3b10ea64..d8b5aa3ef 100644 --- a/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/resources/osl.items.mixins.json +++ b/libraries/items/items-mca1.0.1_01-mc1.6.4/src/main/resources/osl.items.mixins.json @@ -5,18 +5,65 @@ "compatibilityLevel": "JAVA_8", "plugin": "net.ornithemc.osl.items.impl.ItemsMixinPlugin", "mixins": [ + "common.AchievementsMixin", + "common.AxisBlockMixin", "common.BlockItemAccess", + "common.BlockMixin_DropItem", + "common.BlockMixin_SilkTouchDropItem", "common.BlockMixin", "common.BlockMixinNew", "common.BlockMixinOld", + "common.CraftingManagerMixin", + "common.FurnaceBlockEntityMixin", + "common.FurnaceBlockEntityMixinNew", + "common.FurnaceBlockEntityMixinOld", + "common.GravelBlockMixin", + "common.ItemMixin_1_3_1_13w01a", + "common.ItemMixin_13w02a", + "common.ItemMixin_b1_0_1_3", + "common.ItemMixin", "common.ItemMixinNew", - "common.ItemMixinOld" + "common.ItemMixinOld", + "common.ItemStackMixin", + "common.ItemStackMixinNew", + "common.ItemStatAccess", + "common.LeavesBlockMixin", + "common.LootEntryMixinNew", + "common.LootEntryMixinOld", + "common.PaneBlockMixin", + "common.QuartzBlockMixin", + "common.ShapedRecipeMixinNew", + "common.ShapedRecipeMixinOld", + "common.ShapelessRecipeMixin", + "common.SmeltingManagerMixin", + "common.SmeltingManagerMixinNew", + "common.StatsMixin" ], "client": [ + "client.BlockMixin_PickItem", + "client.CustomizeFlatWorldScreen_LayerListWidgetMixin", + "client.ItemInHandRendererMixin", + "client.ItemRendererMixin_b1_4_01_12w34a_13w01a", + "client.ItemRendererMixin_b1_5_12w32a", + "client.ItemRendererMixin_12w50a", + "client.ItemRendererMixin_13w02a", + "client.ItemRendererMixin_1_6", + "client.ItemRendererMixin", + "client.MinecraftMixinMid", + "client.MinecraftMixinNew", + "client.MinecraftMixinOld", + "client.PlayerRendererMixin", + "client.PlayerRendererMixinNew", + "client.SlabBlockMixin", + "client.WitchRendererMixin" ], "server": [ ], "injectors": { - "defaultRequire": 1 + "defaultRequire": 1, + "maxShiftBy": 2 + }, + "mixinextras": { + "minVersion": "0.5.0" } } diff --git a/libraries/registries/README.md b/libraries/registries/README.md new file mode 100644 index 000000000..b780c1db1 --- /dev/null +++ b/libraries/registries/README.md @@ -0,0 +1,114 @@ +# Registries API + +The Registries API provides an alternative to Vanilla's registry system, with a more modern feature set and available for all Minecraft versions. It also provides an API for synchronizing numerical IDs between the server and client and across sessions, to help avoid desync and world corruption bugs. + +## Resource Keys + +Registries are used to keep track of in-game resources. They are assumed to hold all known values of a type, and each value is assigned a unique namespaced identifier. Registries themselves are also registered to their own registry. Thus, a single pair of namespaced identifiers can identify an in-game resource: the first specifies the registry the resource belongs to, and the second identifies the resource within that registry. This is called a `ResourceKey`, and it can be used to refer to a resource without a reference to the actual object. For example, `minecraft:block/minecraft:stone` points to the block `minecraft:stone` in the registry `minecraft:block`. + +The `ResourceKeys` class provides factory methods for creating resource keys: + +```java +ResourceKey COOKIE_KEY = ResourceKeys.from(RegistryKeys.BLOCK, NamespacedIdentifiers.from("example", "cookie")); +``` + +## Registering Resources + +The `Registry` class provides helper methods for registering resources to a registry: + +```java +Block COOKIE = Registry.register(BlockRegistry.REGISTRY, COOKIE_KEY, new CookieBlock()); +``` + +## Creating Registries + +Just like with other resources, you must create a `ResourceKey` that uniquely identifies your registry. The `RegistryKeys` class provides some factory methods for creating resource keys for registries. + +```java +ResourceKey> COOKIE_RECIPE_REGISTRY = RegistryKeys.from(NamespacedIdentifiers.from("example", "cookie_recipe")); +``` + +Registries should be loaded in your mod's entrypoint. The `Registries` class provides helper methods for registering simple and defaulted registries. You can pass along a callback for bootstrapping your registry's contents. + +```java +Registry COOKIE_RECIPE = Registries.registerSimple(COOKIE_RECIPE_REGISTRY, CookieRecipes::init); +``` + +An example setup is shown below. + +```java +package com.example; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +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; + +public class ExampleRegistries { + + public static final ResourceKey> COOKIE_RECIPE_REGISTRY = RegistryKeys.from(NamespacedIdentifiers.from("example", "cookie_recipe")); + + public static final Registry COOKIE_RECIPE = Registries.registerSimple(COOKIE_RECIPE_REGISTRY, CookieRecipes::init); + + public static void init() { + } +} +``` + +```java +package com.example; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; + +public class CookieRecipes { + + public static final CookieRecipe CHOCOLATE_CHIP = Registry.register(ExampleRegistries.COOKIE_RECIPE, NamespacedIdentifiers.from("example", "chocolate_chip"), new ChocolateChipCookieRecipe()); + + public static void init() { + } +} +``` + +```java +package com.example; + +import net.ornithemc.osl.entrypoints.api.ModInitializer; + +public class ExampleInitializer implements ModInitializer { + + @Override + public void init() { + ExampleRegistries.init(); + } +} +``` + +## Registry Sync + +Numerical IDs may be used for serialization in server-client communication or in world saves. If this is the case, you must register your registry to be synchronized. The `SyncedRegistries` class has helper methods for this. An update to the above example is shown below. + +```java +package com.example; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +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; + +public class ExampleRegistries { + + public static final ResourceKey> COOKIE_RECIPE_REGISTRY = RegistryKeys.from(NamespacedIdentifiers.from("example", "cookie_recipe")); + + public static final Registry COOKIE_RECIPE = Registries.registerSimple(COOKIE_RECIPE_REGISTRY, CookieRecipes::init); + + public static void init() { + SyncedRegistries.register(COOKIE_RECIPE_REGISTRY); + } +} +``` + +It is not recommended that you use the numerical IDs in any other places. If it is unavoidable, however, you can register a custom `IdMapper` or `IdFixer` to ensure there are no desync or corruption bugs. This API provides several `IdMapper` implementations you can use, such `BooleanArrayMapper`, `IntArrayMapper`, `ListMapper`, and `Int2ObjectMapMapper`. You can of course create a custom implementation as well. diff --git a/libraries/registries/build.gradle b/libraries/registries/build.gradle new file mode 100644 index 000000000..dddbc1fec --- /dev/null +++ b/libraries/registries/build.gradle @@ -0,0 +1,5 @@ +setUpLibrary(project) + +dependencies { + implementation 'it.unimi.dsi:fastutil:8.5.9' +} diff --git a/libraries/registries/gradle.properties b/libraries/registries/gradle.properties new file mode 100644 index 000000000..403bf484a --- /dev/null +++ b/libraries/registries/gradle.properties @@ -0,0 +1,7 @@ +library_id = registries +library_name = Registries +library_description = Registries API and numerical ID synchronization. +library_version = 0.1.0-alpha.1 + +entrypoint_client_init = net.ornithemc.osl.registries.impl.RegistriesEntrypoint +osl_dependencies = core:>=0.8.0,entrypoints:>=0.5.0,lifecycle-events:>=0.6.0,executors:>=0.1.0,text-components:>=0.1.0-,networking:>=0.9.0,networking-impl:>=0.1.0 diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/build.gradle b/libraries/registries/registries-mc12w18a-mc1.6.4/build.gradle new file mode 100644 index 000000000..0a350fdb3 --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/build.gradle @@ -0,0 +1 @@ +setUpModule(project) diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/gradle.properties b/libraries/registries/registries-mc12w18a-mc1.6.4/gradle.properties new file mode 100644 index 000000000..063af5bd7 --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/gradle.properties @@ -0,0 +1,7 @@ +min_mc_version = 12w18a +max_mc_version = 1.6.4 +minecraft_dependency = >=1.3-alpha.12.18.a <=1.6.4 + +minecraft_version = 1.5.2 +raven_build = 3 +nests_build = 6 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 new file mode 100644 index 000000000..87d5b78ad --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; + +/** + * Utility class containing commonly used registry keys (i.e. @linkplain + * ResourceKey resource keys} for registries), as well as factory methods + * for creating registry keys. + */ +public final class RegistryKeys { + + public static final ResourceKey> BLOCK = from("block"); + public static final ResourceKey> ITEM = from("item"); + + /** + * Constructs a registry key with the default namespace and the given identifier. + * + * @param the value type of the registry. + * @param identifier the identifier of the registry. + * @return the constructed registry key. + */ + public static ResourceKey> from(String identifier) { + return from(NamespacedIdentifiers.from(identifier)); + } + + /** + * Constructs a registry key with the given namespaced identifier. + * + * @param the value type of the registry. + * @param identifier the namespaced identifier of the registry. + * @return the constructed registry key. + */ + public static ResourceKey> from(NamespacedIdentifier identifier) { + return ResourceKeys.from(identifier); + } +} diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/Bootstrap.java b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/Bootstrap.java new file mode 100644 index 000000000..c27f86c9c --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/Bootstrap.java @@ -0,0 +1,18 @@ +package net.ornithemc.osl.registries.impl; + +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +public final class Bootstrap { + + private static boolean initialized; + + public static void init() { + if (!initialized) { + initialized = true; + + RegistriesImpl.init(); + SyncedRegistriesImpl.init(); + } + } +} diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java new file mode 100644 index 000000000..25a4ea674 --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,42 @@ +package net.ornithemc.osl.registries.impl; + +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.api.client.ClientPlayNetworking; +import net.ornithemc.osl.registries.impl.mixin.client.ClientNetworkHandlerAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +public final class RegistriesEntrypoint implements ClientModInitializer { + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(Constants.OSL_REGISTRY_SYNC_CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesPacketSerializer.deserialize(buffer, RegistryMappingSource.REMOTE_SERVER); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.applyMappings(); + }); + } catch (RegistryMappingException e) { + RegistriesImpl.LOGGER.error("Unable to remap registries!", e); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.resetMappings(); + + if (!((ClientNetworkHandlerAccess) context.networkHandler()).accessDisconnected()) { + context.networkHandler().getConnection().disconnect("Failed to remap registries: " + e.getMessage()); + } + }); + } + }); + ClientConnectionEvents.DISCONNECT.register(context -> { + if (!context.isServerLocal()) { + SyncedRegistriesImpl.undoMappings(); + } + }); + } +} diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java new file mode 100644 index 000000000..22ea52172 --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java @@ -0,0 +1,49 @@ +package net.ornithemc.osl.registries.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 RegistriesMixinPlugin implements IMixinConfigPlugin { + + @Override + public void onLoad(String mixinPackage) { + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if ("net.ornithemc.osl.registries.impl.mixin.client.IntegratedServerMixin".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("12w25a") >= 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/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java new file mode 100644 index 000000000..ea596a58c --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java @@ -0,0 +1,11 @@ +package net.ornithemc.osl.registries.impl.access; + +import java.io.IOException; + +public interface WorldStorageAccess { + + void osl$registries$loadRegistryMappings() throws IOException; + + void osl$registries$saveRegistryMappings() throws IOException; + +} diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/ClientNetworkHandlerAccess.java b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..ffe477a57 --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/ClientNetworkHandlerAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.client.network.handler.ClientNetworkHandler; + +@Mixin(ClientNetworkHandler.class) +public interface ClientNetworkHandlerAccess { + + @Accessor("disconnected") + boolean accessDisconnected(); + +} diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java new file mode 100644 index 000000000..14c262879 --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java @@ -0,0 +1,50 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import java.io.IOException; + +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.At.Shift; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.world.storage.WorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(IntegratedServer.class) +public class IntegratedServerMixin { + + @Inject( + method = "loadWorld", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/storage/WorldStorageSource;get(Ljava/lang/String;Z)Lnet/minecraft/world/storage/WorldStorage;", + shift = Shift.BY, + by = 2 + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci, @Local WorldStorage storage) { + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$loadRegistryMappings(); + } catch (IOException e) { + throw new RuntimeException("Exception initializing level", e); + } + } + } + + @Inject( + method = "shutdown", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$unmapRegistries(CallbackInfo ci) { + SyncedRegistriesImpl.undoMappings(); + } +} diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/MinecraftMixin.java b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/MinecraftMixin.java new file mode 100644 index 000000000..107f853f6 --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/MinecraftMixin.java @@ -0,0 +1,27 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +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.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; + +import net.ornithemc.osl.registries.impl.Bootstrap; + +@Mixin(Minecraft.class) +public class MinecraftMixin { + + @Inject( + method = "", + at = @At( + value = "INVOKE", + target = "Ljava/lang/Object;()V", + shift = Shift.AFTER + ) + ) + private void osl$registries$bootstrap(CallbackInfo ci) { + Bootstrap.init(); + } +} diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java new file mode 100644 index 000000000..f7de606ca --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,116 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.storage.AlphaWorldStorage; + +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesNbtSerializer; + +@Mixin(AlphaWorldStorage.class) +public class AlphaWorldStorageMixin implements WorldStorageAccess { + + @Shadow @Final + private String name; + + @Shadow + private File getDirectory() { return null; } + + @Override + public void osl$registries$loadRegistryMappings() throws IOException { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + + if (!this.readRegistryMappings(file, false)) { + file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + if (!this.readRegistryMappings(file, true)) { + RegistriesImpl.LOGGER.debug("no registry mappings read for '" + this.name + "'"); + } + } + } + + @Unique + private boolean readRegistryMappings(File file, boolean throwOnException) throws IOException { + if (file.exists()) { + try (InputStream is = new FileInputStream(file)) { + NbtCompound nbt = NbtIo.readCompressed(is); + + SyncedRegistriesNbtSerializer.deserialize(nbt, RegistryMappingSource.WORLD_SAVE); + SyncedRegistriesImpl.applyMappings(); + + return true; + } catch (IOException e) { + if (throwOnException) { + throw new IOException("Unable to read registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("error while reading registry mappings for '" + this.name + "'", e); + } + } catch (RegistryMappingException e) { + if (throwOnException) { + throw new IOException("Invalid registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("invalid registry mappings for '" + this.name + "'", e); + } + } + } + + return false; + } + + @Override + public void osl$registries$saveRegistryMappings() throws IOException { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + File tmp = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_tmp"); + File backup = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + this.writeRegistryMappings(file, tmp, backup); + } + + @Unique + private void writeRegistryMappings(File file, File newFile, File oldFile) throws IOException { + NbtCompound nbt = new NbtCompound(); + + try { + SyncedRegistriesNbtSerializer.serialize(nbt); + + try (OutputStream os = new FileOutputStream(newFile)) { + NbtIo.writeCompressed(nbt, os); + } + + if (oldFile.exists()) { + oldFile.delete(); + } + + file.renameTo(oldFile); + if (file.exists()) { + file.delete(); + } + + newFile.renameTo(file); + if (newFile.exists()) { + newFile.delete(); + } + } catch (IOException e) { + RegistriesImpl.LOGGER.warn("error while writing registry mappings for '" + this.name + "'", e); + } + } +} diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java new file mode 100644 index 000000000..b78e237c1 --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java @@ -0,0 +1,59 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.IOException; + +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.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.storage.WorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + + @Inject( + method = "loadWorld", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/storage/WorldStorage;loadData()Lnet/minecraft/world/WorldData;" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci, @Local WorldStorage storage) { + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$loadRegistryMappings(); + } catch (IOException e) { + throw new RuntimeException("Exception initializing level", e); + } + } + } + + @Inject( + method = "saveWorlds", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(CallbackInfo ci) { + MinecraftServer server = (MinecraftServer) (Object) this; + + ServerWorld overworld = server.worlds[0]; + WorldStorage storage = overworld.getStorage(); + + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$saveRegistryMappings(); + } catch (IOException e) { + RegistriesImpl.LOGGER.error("Exception saving level", e); + } + } + } +} diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/NbtCompoundAccess.java b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/NbtCompoundAccess.java new file mode 100644 index 000000000..91ac96618 --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/NbtCompoundAccess.java @@ -0,0 +1,17 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Map; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; + +@Mixin(NbtCompound.class) +public interface NbtCompoundAccess { + + @Accessor("elements") + Map accessElements(); + +} diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java new file mode 100644 index 000000000..f9fb53d5d --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.registries.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 com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.mob.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerPlayNetworking; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final + private MinecraftServer server; + + @Inject( + method = "onLogin", + at = @At( + value = "NEW", + target = "net/minecraft/network/packet/LoginPacket" + ) + ) + private void osl$idsync$syncRegistries(CallbackInfo ci, @Local ServerPlayerEntity player) { + if (this.server.isDedicated() || !this.server.getUsername().equals(player.getName())) { + ServerPlayNetworking.sendNoCheck(player, Constants.OSL_REGISTRY_SYNC_CHANNEL, SyncedRegistriesPacketSerializer::serialize); + } + } +} diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/MinecraftServerMixin.java b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/MinecraftServerMixin.java new file mode 100644 index 000000000..879f51ea3 --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/MinecraftServerMixin.java @@ -0,0 +1,27 @@ +package net.ornithemc.osl.registries.impl.mixin.server; + +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.server.MinecraftServer; + +import net.ornithemc.osl.registries.impl.Bootstrap; + +@Mixin( + value = MinecraftServer.class, + priority = 1001 // make sure entrypoints mixin is applied first +) +public class MinecraftServerMixin { + + @Inject( + method = "main", + at = @At( + value = "HEAD" + ) + ) + private static void osl$registries$bootstrap(CallbackInfo ci) { + Bootstrap.init(); + } +} diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java new file mode 100644 index 000000000..131111816 --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java @@ -0,0 +1,79 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.minecraft.nbt.NbtCompound; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.mixin.common.NbtCompoundAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesNbtSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(NbtCompound nbt) throws IOException { + NbtCompound registriesNbt = new NbtCompound(); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt, SyncedRegistriesNbtSerializer::serialize); + registriesNbt.put(identifier.toString(), mappingsNbt); + } + + nbt.putInt(Constants.FORMAT_NBT_KEY, Constants.REGISTRY_MAPPINGS_FORMAT); + nbt.put(Constants.REGISTRIES_NBT_KEY, registriesNbt); + } + + public static void deserialize(NbtCompound nbt, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = nbt.getInt(Constants.FORMAT_NBT_KEY); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + NbtCompound registriesNbt = nbt.getCompound(Constants.REGISTRIES_NBT_KEY); + + for (String key : ((NbtCompoundAccess) registriesNbt).accessElements().keySet()) { + NbtCompound mappingsNbt = registriesNbt.getCompound(key); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(key); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(mappingsNbt, SyncedRegistriesNbtSerializer::deserialize, source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(NbtCompound nbt, Object2IntMap mappings) throws IOException { + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } + + public static void deserialize(NbtCompound nbt, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + for (String key : ((NbtCompoundAccess) nbt).accessElements().keySet()) { + mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + } +} diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java new file mode 100644 index 000000000..d21165816 --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java @@ -0,0 +1,81 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesPacketSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(Constants.REGISTRY_MAPPINGS_FORMAT); + buffer.writeVarInt(REGISTRIES.keySet().size()); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer, SyncedRegistriesPacketSerializer::serialize); + } + } + + public static void deserialize(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(buffer, SyncedRegistriesPacketSerializer::deserialize, source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(PacketBuffer buffer, Object2IntMap mappings) throws IOException { + buffer.writeVarInt(mappings.size()); + + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public static void deserialize(PacketBuffer buffer, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + mappings.put(identifier, id); + } + } +} diff --git a/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/resources/fabric.mod.json b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..b77726cce --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/resources/fabric.mod.json @@ -0,0 +1,36 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc12w18a-mc1.6.4", + "environment": "*", + "entrypoints": { + "client-init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ] + }, + "mixins": [ + "osl.registries.mixins.json" + ], + "depends": { + "fabricloader": "\u003e\u003d0.18.0", + "minecraft": "\u003e\u003d1.3-alpha.12.18.a \u003c\u003d1.6.4", + "osl-core": "\u003e\u003d0.8.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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0" + }, + "name": "OSL Registries", + "description": "Registries API and numerical ID synchronization.", + "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/registries/registries-mc12w18a-mc1.6.4/src/main/resources/osl.registries.mixins.json b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/resources/osl.registries.mixins.json new file mode 100644 index 000000000..f43126613 --- /dev/null +++ b/libraries/registries/registries-mc12w18a-mc1.6.4/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,25 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "plugin": "net.ornithemc.osl.registries.impl.RegistriesMixinPlugin", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.MinecraftServerMixin", + "common.NbtCompoundAccess", + "common.PlayerManagerMixin" + ], + "client": [ + "client.ClientNetworkHandlerAccess", + "client.IntegratedServerMixin", + "client.MinecraftMixin" + ], + "server": [ + "server.MinecraftServerMixin" + ], + "injectors": { + "defaultRequire": 1, + "maxShiftBy": 2 + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/build.gradle b/libraries/registries/registries-mc13w36a-mc14w26c/build.gradle new file mode 100644 index 000000000..0a350fdb3 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/build.gradle @@ -0,0 +1 @@ +setUpModule(project) diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/gradle.properties b/libraries/registries/registries-mc13w36a-mc14w26c/gradle.properties new file mode 100644 index 000000000..1cad83f51 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/gradle.properties @@ -0,0 +1,8 @@ +min_mc_version = 13w36a +max_mc_version = 14w26c +minecraft_dependency = >=1.7-alpha.13.36.a <=1.8-alpha.14.26.c + +minecraft_version = 1.7.2 +raven_build = 1 +sparrow_build = 1 +nests_build = 3 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 new file mode 100644 index 000000000..87d5b78ad --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; + +/** + * Utility class containing commonly used registry keys (i.e. @linkplain + * ResourceKey resource keys} for registries), as well as factory methods + * for creating registry keys. + */ +public final class RegistryKeys { + + public static final ResourceKey> BLOCK = from("block"); + public static final ResourceKey> ITEM = from("item"); + + /** + * Constructs a registry key with the default namespace and the given identifier. + * + * @param the value type of the registry. + * @param identifier the identifier of the registry. + * @return the constructed registry key. + */ + public static ResourceKey> from(String identifier) { + return from(NamespacedIdentifiers.from(identifier)); + } + + /** + * Constructs a registry key with the given namespaced identifier. + * + * @param the value type of the registry. + * @param identifier the namespaced identifier of the registry. + * @return the constructed registry key. + */ + public static ResourceKey> from(NamespacedIdentifier identifier) { + return ResourceKeys.from(identifier); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java new file mode 100644 index 000000000..f6896b0bd --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,43 @@ +package net.ornithemc.osl.registries.impl; + +import net.minecraft.text.LiteralText; + +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.api.client.ClientPlayNetworking; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +public final class RegistriesEntrypoint implements ClientModInitializer { + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(Constants.OSL_REGISTRY_SYNC_CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesPacketSerializer.deserialize(buffer, RegistryMappingSource.REMOTE_SERVER); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.applyMappings(); + }); + } catch (RegistryMappingException e) { + RegistriesImpl.LOGGER.error("Unable to remap registries!", e); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.resetMappings(); + + if (context.networkHandler().getConnection().isConnected()) { + context.networkHandler().getConnection().disconnect(new LiteralText("Failed to remap registries: " + e.getMessage())); + } + }); + } + }); + ClientConnectionEvents.DISCONNECT.register(context -> { + if (!context.isServerLocal()) { + SyncedRegistriesImpl.undoMappings(); + } + }); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java new file mode 100644 index 000000000..a3395d4da --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java @@ -0,0 +1,55 @@ +package net.ornithemc.osl.registries.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 RegistriesMixinPlugin implements IMixinConfigPlugin { + + @Override + public void onLoad(String mixinPackage) { + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if ("net.ornithemc.osl.registries.impl.mixin.common.CrudeIncrementalIntIdentityHashMapMixin".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("1.7.10-pre3") < 0 || (MinecraftVersion.resolve().compareTo("14w02a") >= 0 && MinecraftVersion.resolve().compareTo("14w25a") < 0); + } + if ("net.ornithemc.osl.registries.impl.mixin.common.CrudeIncrementalIntIdentityHashMapMixin_1_7_10_pre3".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("1.7.10-pre3") >= 0 && MinecraftVersion.resolve().compareTo("1.7.10") <= 0; + } + if ("net.ornithemc.osl.registries.impl.mixin.common.CrudeIncrementalIntIdentityHashMapMixin_14w25a".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("14w25a") >= 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/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java new file mode 100644 index 000000000..d7017be43 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java @@ -0,0 +1,16 @@ +package net.ornithemc.osl.registries.impl.access; + +public interface Clearable { + + static void clear(Object o) { + if (o instanceof Clearable) { + ((Clearable) o).osl$registries$clear(); + } else { + throw new IllegalArgumentException("not clearable: " + o); + } + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java new file mode 100644 index 000000000..3446d3162 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java @@ -0,0 +1,18 @@ +package net.ornithemc.osl.registries.impl.access; + +public interface IdRegistryAccess { + + default void osl$registries$setCallback(RegisterCallback callback) { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } + + interface RegisterCallback { + + void valueRegistered(int id, String key, Object value); + + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java new file mode 100644 index 000000000..ea596a58c --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java @@ -0,0 +1,11 @@ +package net.ornithemc.osl.registries.impl.access; + +import java.io.IOException; + +public interface WorldStorageAccess { + + void osl$registries$loadRegistryMappings() throws IOException; + + void osl$registries$saveRegistryMappings() throws IOException; + +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java new file mode 100644 index 000000000..12ddba1d4 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java @@ -0,0 +1,52 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import java.io.IOException; + +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.At.Shift; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.util.crash.CrashException; +import net.minecraft.util.crash.CrashReport; +import net.minecraft.world.storage.WorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(IntegratedServer.class) +public class IntegratedServerMixin { + + @Inject( + method = "loadWorld", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/storage/WorldStorageSource;get(Ljava/lang/String;Z)Lnet/minecraft/world/storage/WorldStorage;", + shift = Shift.BY, + by = 2 + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci, @Local WorldStorage storage) { + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$loadRegistryMappings(); + } catch (IOException e) { + throw new CrashException(CrashReport.of(e, "Exception initializing level")); + } + } + } + + @Inject( + method = "shutdown", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$unmapRegistries(CallbackInfo ci) { + SyncedRegistriesImpl.undoMappings(); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java new file mode 100644 index 000000000..f7de606ca --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,116 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.storage.AlphaWorldStorage; + +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesNbtSerializer; + +@Mixin(AlphaWorldStorage.class) +public class AlphaWorldStorageMixin implements WorldStorageAccess { + + @Shadow @Final + private String name; + + @Shadow + private File getDirectory() { return null; } + + @Override + public void osl$registries$loadRegistryMappings() throws IOException { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + + if (!this.readRegistryMappings(file, false)) { + file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + if (!this.readRegistryMappings(file, true)) { + RegistriesImpl.LOGGER.debug("no registry mappings read for '" + this.name + "'"); + } + } + } + + @Unique + private boolean readRegistryMappings(File file, boolean throwOnException) throws IOException { + if (file.exists()) { + try (InputStream is = new FileInputStream(file)) { + NbtCompound nbt = NbtIo.readCompressed(is); + + SyncedRegistriesNbtSerializer.deserialize(nbt, RegistryMappingSource.WORLD_SAVE); + SyncedRegistriesImpl.applyMappings(); + + return true; + } catch (IOException e) { + if (throwOnException) { + throw new IOException("Unable to read registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("error while reading registry mappings for '" + this.name + "'", e); + } + } catch (RegistryMappingException e) { + if (throwOnException) { + throw new IOException("Invalid registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("invalid registry mappings for '" + this.name + "'", e); + } + } + } + + return false; + } + + @Override + public void osl$registries$saveRegistryMappings() throws IOException { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + File tmp = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_tmp"); + File backup = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + this.writeRegistryMappings(file, tmp, backup); + } + + @Unique + private void writeRegistryMappings(File file, File newFile, File oldFile) throws IOException { + NbtCompound nbt = new NbtCompound(); + + try { + SyncedRegistriesNbtSerializer.serialize(nbt); + + try (OutputStream os = new FileOutputStream(newFile)) { + NbtIo.writeCompressed(nbt, os); + } + + if (oldFile.exists()) { + oldFile.delete(); + } + + file.renameTo(oldFile); + if (file.exists()) { + file.delete(); + } + + newFile.renameTo(file); + if (newFile.exists()) { + newFile.delete(); + } + } catch (IOException e) { + RegistriesImpl.LOGGER.warn("error while writing registry mappings for '" + this.name + "'", e); + } + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java new file mode 100644 index 000000000..b27f392a5 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; + +import net.minecraft.Bootstrap; + +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(Bootstrap.class) +public class BootstrapMixin { + + @Shadow + private static boolean initialized; + + @WrapMethod(method = "init()V") + private static void osl$registries$initAndLockRegistries(Operation op) { + boolean wasInitialized = initialized; + + // we could skip the call if initialized is already true + // but let's not mess with the bootstrap too much, eh + op.call(); + + if (!wasInitialized) { + RegistriesImpl.init(); + SyncedRegistriesImpl.init(); + } + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java new file mode 100644 index 000000000..0eee3e7dc --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java @@ -0,0 +1,27 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import gnu.trove.map.hash.TIntIntHashMap; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; + +import net.ornithemc.osl.registries.impl.access.Clearable; + +@Mixin(CrudeIncrementalIntIdentityHashMap.class) +public class CrudeIncrementalIntIdentityHashMapMixin implements Clearable { + + @Shadow + private TIntIntHashMap ids; + @Shadow + private List values; + + @Override + public void osl$registries$clear() { + this.ids.clear(); + this.values.clear(); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin_14w25a.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin_14w25a.java new file mode 100644 index 000000000..b987a5aa8 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin_14w25a.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.IdentityHashMap; +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; + +import net.ornithemc.osl.registries.impl.access.Clearable; + +@Mixin(CrudeIncrementalIntIdentityHashMap.class) +public class CrudeIncrementalIntIdentityHashMapMixin_14w25a implements Clearable { + + @Shadow + private IdentityHashMap f_29800171; // ids + @Shadow + private List f_87828088; // values + + @Override + public void osl$registries$clear() { + this.f_29800171.clear(); + this.f_87828088.clear(); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin_1_7_10_pre3.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin_1_7_10_pre3.java new file mode 100644 index 000000000..67577b682 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin_1_7_10_pre3.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.IdentityHashMap; +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; + +import net.ornithemc.osl.registries.impl.access.Clearable; + +@Mixin(CrudeIncrementalIntIdentityHashMap.class) +public class CrudeIncrementalIntIdentityHashMapMixin_1_7_10_pre3 implements Clearable { + + @Shadow + private IdentityHashMap f_29800171; // ids + @Shadow + private List f_87828088; // values + + @Override + public void osl$registries$clear() { + this.f_29800171.clear(); + this.f_87828088.clear(); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java new file mode 100644 index 000000000..ea2c60afe --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.util.registry.DefaultedIdRegistry; + +@Mixin(DefaultedIdRegistry.class) +public interface DefaultedIdRegistryAccess { + + @Accessor("defaultKey") + String accessDefaultKey(); + +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java new file mode 100644 index 000000000..273b5eca8 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java @@ -0,0 +1,80 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Map; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +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.util.CrudeIncrementalIntIdentityHashMap; +import net.minecraft.util.registry.IdRegistry; +import net.minecraft.util.registry.MappedRegistry; + +import net.ornithemc.osl.registries.impl.access.Clearable; +import net.ornithemc.osl.registries.impl.access.IdRegistryAccess; + +@Mixin(IdRegistry.class) +public class IdRegistryMixin extends MappedRegistry implements IdRegistryAccess, Clearable { + + @Shadow @Final + private CrudeIncrementalIntIdentityHashMap ids; + @Shadow @Final + private Map keys; + + @Unique + private RegisterCallback callback; + @Unique + private int nextId; + + @Shadow + private void register(int id, String key, T value) { } + + @Redirect( + method = "register", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/util/registry/IdRegistry;put(Ljava/lang/Object;Ljava/lang/Object;)V" + ) + ) + private void osl$registries$replaceThisPutWithSuperPut(IdRegistry self, Object key, T value) { + super.put((String) key, value); + } + + @Inject( + method = "register", + at = @At( + value = "RETURN" + ) + ) + private void osl$registries$register(int id, String key, T value, CallbackInfo ci) { + this.nextId = Math.max(this.nextId, id + 1); + + if (this.callback != null) { + this.callback.valueRegistered(id, key, value); + } + } + + @Override + public void put(String key, T value) { + this.register(this.nextId, key, value); + } + + @Override + public void osl$registries$setCallback(RegisterCallback callback) { + this.callback = callback; + } + + @Override + public void osl$registries$clear() { + this.entries.clear(); + this.keys.clear(); + Clearable.clear(this.ids); + + this.nextId = 0; + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java new file mode 100644 index 000000000..61a318c15 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java @@ -0,0 +1,61 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.IOException; + +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.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.crash.CrashException; +import net.minecraft.util.crash.CrashReport; +import net.minecraft.world.storage.WorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + + @Inject( + method = "loadWorld", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/storage/WorldStorage;loadData()Lnet/minecraft/world/WorldData;" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci, @Local WorldStorage storage) { + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$loadRegistryMappings(); + } catch (IOException e) { + throw new CrashException(CrashReport.of(e, "Exception initializing level")); + } + } + } + + @Inject( + method = "saveWorlds", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(CallbackInfo ci) { + MinecraftServer server = (MinecraftServer) (Object) this; + + ServerWorld overworld = server.worlds[0]; + WorldStorage storage = overworld.getStorage(); + + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$saveRegistryMappings(); + } catch (IOException e) { + RegistriesImpl.LOGGER.error("Exception saving level", e); + } + } + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java new file mode 100644 index 000000000..37a827c2d --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.registries.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 com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerPlayNetworking; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final + private MinecraftServer server; + + @Inject( + method = "onLogin", + at = @At( + value = "NEW", + target = "net/minecraft/network/packet/s2c/play/LoginS2CPacket" + ) + ) + private void osl$idsync$syncRegistries(CallbackInfo ci, @Local ServerPlayerEntity player) { + if (this.server.isDedicated() || !this.server.getUsername().equals(player.getName())) { + ServerPlayNetworking.sendNoCheck(player, Constants.OSL_REGISTRY_SYNC_CHANNEL, SyncedRegistriesPacketSerializer::serialize); + } + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/StatAccess.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/StatAccess.java new file mode 100644 index 000000000..2432b20e9 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/StatAccess.java @@ -0,0 +1,16 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.stat.Stat; + +@Mixin(Stat.class) +public interface StatAccess { + + @Mutable + @Accessor("key") + void setKey(String key); + +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java new file mode 100644 index 000000000..d5e0ea8eb --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java @@ -0,0 +1,29 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.function.Supplier; + +import net.minecraft.util.registry.DefaultedIdRegistry; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public final class VanillaRegistries { + + public static Registry registerSimple(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return registerSimple(key, registry, () -> null); + } + + public static Registry registerSimple(ResourceKey> key, net.minecraft.util.registry.Registry registry, Supplier bootstrap) { + return RegistriesImpl.register(key, WrappedIdRegistry.of(key, (IdRegistry) registry), bootstrap::get); + } + + public static DefaultedRegistry registerDefaulted(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return registerDefaulted(key, registry, () -> null); + } + + public static DefaultedRegistry registerDefaulted(ResourceKey> key, net.minecraft.util.registry.Registry registry, Supplier bootstrap) { + return RegistriesImpl.register(key, WrappedDefaultedIdRegistry.of(key, (DefaultedIdRegistry) registry), bootstrap::get); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java new file mode 100644 index 000000000..2c6ff3324 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java @@ -0,0 +1,25 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.util.registry.DefaultedIdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.impl.mixin.common.DefaultedIdRegistryAccess; + +public class WrappedDefaultedIdRegistry extends WrappedIdRegistry implements DefaultedRegistry { + + public static WrappedDefaultedIdRegistry of(ResourceKey> key, DefaultedIdRegistry registry) { + return new WrappedDefaultedIdRegistry<>(key.identifier(), registry); + } + + private WrappedDefaultedIdRegistry(NamespacedIdentifier identifier, DefaultedIdRegistry registry) { + super(identifier, registry); + } + + @Override + public NamespacedIdentifier getDefaultIdentifier() { + return this.serializeKey(((DefaultedIdRegistryAccess) this.registry).accessDefaultKey()); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java new file mode 100644 index 000000000..29f127934 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java @@ -0,0 +1,131 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.Iterator; +import java.util.Set; +import java.util.stream.Collectors; + +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.ResourceKeys; + +public class WrappedIdRegistry implements ClearableRegistry { + + public static WrappedIdRegistry of(ResourceKey> key, IdRegistry registry) { + return new WrappedIdRegistry<>(key.identifier(), registry); + } + + final NamespacedIdentifier identifier; + final IdRegistry registry; + + private int nextId; + private boolean frozen; + + WrappedIdRegistry(NamespacedIdentifier identifier, IdRegistry registry) { + this.identifier = identifier; + this.registry = registry; + + this.registry.osl$registries$setCallback(this::valueRegistered); + } + + NamespacedIdentifier serializeKey(String key) { + return key == null ? null : NamespacedIdentifiers.parse(key); + } + + String deserializeKey(NamespacedIdentifier identifier) { + return identifier == null ? null : identifier.toString(); + } + + ResourceKey resourceKey(NamespacedIdentifier identifier) { + return identifier == null ? null : ResourceKeys.from(this.identifier, identifier); + } + + private void valueRegistered(int id, String key, Object value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + + this.nextId = Math.max(this.nextId, id + 1); + } + + @Override + public V register(ResourceKey key, V value) { + return this.register(this.nextId, key, value); + } + + @Override + public V register(int id, ResourceKey key, V value) { + this.registry.register(id, this.deserializeKey(key.identifier()), value); + return value; + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } + + @Override + public T get(int id) { + return this.registry.get(id); + } + + @Override + public T get(ResourceKey key) { + return this.registry.get(this.deserializeKey(key.identifier())); + } + + @Override + public T get(NamespacedIdentifier identifier) { + return this.registry.get(this.deserializeKey(identifier)); + } + + @Override + public int getId(T value) { + return this.registry.getId(value); + } + + @Override + public ResourceKey getKey(T value) { + return this.resourceKey(this.serializeKey(this.registry.getKey(value))); + } + + @Override + public NamespacedIdentifier getIdentifier(T value) { + return this.serializeKey(this.registry.getKey(value)); + } + + @Override + public Set> keySet() { + return this.registry.keySet().stream().map(this::serializeKey).map(this::resourceKey).collect(Collectors.toSet()); + } + + @Override + public Set identifierSet() { + return this.registry.keySet().stream().map(this::serializeKey).collect(Collectors.toSet()); + } + + @Override + public Iterator iterator() { + return this.registry.iterator(); + } + + @Override + public Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public void clear() { + this.registry.osl$registries$clear(); + + this.nextId = 0; + this.frozen = false; + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/StatsMapper.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/StatsMapper.java new file mode 100644 index 000000000..6d66d4407 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/StatsMapper.java @@ -0,0 +1,97 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import it.unimi.dsi.fastutil.ints.Int2IntFunction; + +import net.minecraft.stat.Stat; + +import net.ornithemc.osl.registries.api.registry.sync.IdMapper; +import net.ornithemc.osl.registries.api.registry.sync.ObjectArrayMapper; +import net.ornithemc.osl.registries.api.registry.sync.RegistryMappings; +import net.ornithemc.osl.registries.impl.mixin.common.StatAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +public class StatsMapper implements IdMapper { + + public static StatsMapper of(Map stats, Stat[] registry) { + return new StatsMapper(stats, registry); + } + + private final ObjectArrayMapper registryMapper; + + private final Stat[] registry; + private final Map stats; + private final Map missing; + + private boolean applied; + + private StatsMapper(Map stats, Stat[] registry) { + this.registryMapper = ObjectArrayMapper.of(registry); + + this.registry = registry; + this.stats = stats; + this.missing = new HashMap<>(); + } + + @Override + public void apply(RegistryMappings mappings) { + this.missing.clear(); + this.fixKeys(mappings::remap, true); + + this.registryMapper.apply(mappings); + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + this.registryMapper.undo(mappings); + + if (this.applied) { + this.fixKeys(mappings::unmap, false); + this.stats.putAll(this.missing); + } + + this.applied = false; + } + + private void fixKeys(Int2IntFunction mapper, boolean storeMissingStats) { + Map fixed = new HashMap<>(); + + // some blocks/items share a single Stat! + Arrays.stream(this.registry).distinct().forEach(stat -> { + if (stat == null) { + return; + } + + int i = stat.key.lastIndexOf('.'); + String base = stat.key.substring(0, i + 1); + String id = stat.key.substring(i + 1); + + try { + int oldId = Integer.parseInt(id); + int newId = mapper.applyAsInt(oldId); + + if (oldId != newId) { + this.stats.remove(stat.key); + + if (newId >= 0) { + StatAccess statAccess = (StatAccess) stat; + statAccess.setKey(base + newId); + + fixed.put(stat.key, stat); + } else if (storeMissingStats) { + this.missing.put(stat.key, stat); + } + } + } catch (NumberFormatException e) { + RegistriesImpl.LOGGER.warn("Stat key {} does not follow expected format of 'statType.'", stat.key); + } + }); + + this.stats.putAll(fixed); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java new file mode 100644 index 000000000..b2b48ca34 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java @@ -0,0 +1,78 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.minecraft.nbt.NbtCompound; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesNbtSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(NbtCompound nbt) throws IOException { + NbtCompound registriesNbt = new NbtCompound(); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt, SyncedRegistriesNbtSerializer::serialize); + registriesNbt.put(identifier.toString(), mappingsNbt); + } + + nbt.putInt(Constants.FORMAT_NBT_KEY, Constants.REGISTRY_MAPPINGS_FORMAT); + nbt.put(Constants.REGISTRIES_NBT_KEY, registriesNbt); + } + + public static void deserialize(NbtCompound nbt, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = nbt.getInt(Constants.FORMAT_NBT_KEY); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + NbtCompound registriesNbt = nbt.getCompound(Constants.REGISTRIES_NBT_KEY); + + for (String key : registriesNbt.getKeys()) { + NbtCompound mappingsNbt = registriesNbt.getCompound(key); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(key); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(mappingsNbt, SyncedRegistriesNbtSerializer::deserialize, source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(NbtCompound nbt, Object2IntMap mappings) throws IOException { + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } + + public static void deserialize(NbtCompound nbt, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + for (String key : nbt.getKeys()) { + mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java new file mode 100644 index 000000000..d21165816 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java @@ -0,0 +1,81 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesPacketSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(Constants.REGISTRY_MAPPINGS_FORMAT); + buffer.writeVarInt(REGISTRIES.keySet().size()); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer, SyncedRegistriesPacketSerializer::serialize); + } + } + + public static void deserialize(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(buffer, SyncedRegistriesPacketSerializer::deserialize, source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(PacketBuffer buffer, Object2IntMap mappings) throws IOException { + buffer.writeVarInt(mappings.size()); + + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public static void deserialize(PacketBuffer buffer, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + mappings.put(identifier, id); + } + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/fabric.mod.json b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..faa20f931 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/fabric.mod.json @@ -0,0 +1,37 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc13w36a-mc14w26c", + "environment": "*", + "entrypoints": { + "client-init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ] + }, + "mixins": [ + "osl.registries.mixins.json" + ], + "accessWidener": "osl.registries.classtweaker", + "depends": { + "fabricloader": "\u003e\u003d0.18.0", + "minecraft": "\u003e\u003d1.7-alpha.13.36.a \u003c\u003d1.8-alpha.14.26.c", + "osl-core": "\u003e\u003d0.8.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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0" + }, + "name": "OSL Registries", + "description": "Registries API and numerical ID synchronization.", + "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/registries/registries-mc13w36a-mc14w26c/src/main/resources/osl.registries.classtweaker b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/osl.registries.classtweaker new file mode 100644 index 000000000..e4876667d --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/osl.registries.classtweaker @@ -0,0 +1,3 @@ +classTweaker v1 named + +inject-interface net/minecraft/util/registry/IdRegistry net/ornithemc/osl/registries/impl/access/IdRegistryAccess diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/osl.registries.mixins.json b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/osl.registries.mixins.json new file mode 100644 index 000000000..ec43bef0e --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,28 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "plugin": "net.ornithemc.osl.registries.impl.RegistriesMixinPlugin", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.BootstrapMixin", + "common.CrudeIncrementalIntIdentityHashMapMixin", + "common.CrudeIncrementalIntIdentityHashMapMixin_1_7_10_pre3", + "common.CrudeIncrementalIntIdentityHashMapMixin_14w25a", + "common.DefaultedIdRegistryAccess", + "common.IdRegistryMixin", + "common.MinecraftServerMixin", + "common.PlayerManagerMixin", + "common.StatAccess" + ], + "client": [ + "client.IntegratedServerMixin" + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1, + "maxShiftBy": 2 + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/build.gradle b/libraries/registries/registries-mc14w27a-mc17w46a/build.gradle new file mode 100644 index 000000000..0a350fdb3 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/build.gradle @@ -0,0 +1 @@ +setUpModule(project) diff --git a/libraries/blocks/blocks-mc14w27a-mc17w46a/gradle.properties b/libraries/registries/registries-mc14w27a-mc17w46a/gradle.properties similarity index 80% rename from libraries/blocks/blocks-mc14w27a-mc17w46a/gradle.properties rename to libraries/registries/registries-mc14w27a-mc17w46a/gradle.properties index 5d811d735..6b9ea8e51 100644 --- a/libraries/blocks/blocks-mc14w27a-mc17w46a/gradle.properties +++ b/libraries/registries/registries-mc14w27a-mc17w46a/gradle.properties @@ -3,3 +3,5 @@ max_mc_version = 17w46a minecraft_dependency = >=1.8-alpha.14.27.a <=1.13-alpha.17.46.a minecraft_version = 1.12.2 +raven_build = 1 +sparrow_build = 1 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 new file mode 100644 index 000000000..87d5b78ad --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; + +/** + * Utility class containing commonly used registry keys (i.e. @linkplain + * ResourceKey resource keys} for registries), as well as factory methods + * for creating registry keys. + */ +public final class RegistryKeys { + + public static final ResourceKey> BLOCK = from("block"); + public static final ResourceKey> ITEM = from("item"); + + /** + * Constructs a registry key with the default namespace and the given identifier. + * + * @param the value type of the registry. + * @param identifier the identifier of the registry. + * @return the constructed registry key. + */ + public static ResourceKey> from(String identifier) { + return from(NamespacedIdentifiers.from(identifier)); + } + + /** + * Constructs a registry key with the given namespaced identifier. + * + * @param the value type of the registry. + * @param identifier the namespaced identifier of the registry. + * @return the constructed registry key. + */ + public static ResourceKey> from(NamespacedIdentifier identifier) { + return ResourceKeys.from(identifier); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java new file mode 100644 index 000000000..544daace9 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java @@ -0,0 +1,67 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import net.minecraft.util.Id2ObjectBiMap; + +/** + * An {@linkplain IdMapper} implementation for {@linkplain Id2ObjectBiMap}s + * where IDs are used as keys to the map. The values are moved from the old key + * (the old ID) to the new key (the new ID) within the same map. {@code null} is + * used as the default or "empty" value. + */ +public class Id2ObjectBiMapMapper implements IdMapper { + + public static Id2ObjectBiMapMapper of(Id2ObjectBiMap registry) { + return new Id2ObjectBiMapMapper(registry); + } + + private final Id2ObjectBiMap registry; + private final Id2ObjectBiMap backup; + + private boolean applied; + + @SuppressWarnings("unchecked") + private Id2ObjectBiMapMapper(Id2ObjectBiMap registry) { + this.registry = (Id2ObjectBiMap) registry; + this.backup = new Id2ObjectBiMap<>(registry.size()); + } + + /* + * unlike Registry, Id2ObjectBiMap allows duplicate values + * thus iterating over all values will not give you all id-value pairs! + */ + + @Override + public void apply(RegistryMappings mappings) { + this.backup.osl$registries$clear(); + + for (int id : this.registry.osl$registries$idSet()) { + this.backup.put(this.registry.get(id), id); + } + + this.registry.osl$registries$clear(); + + for (int oldId : this.backup.osl$registries$idSet()) { + Object value = this.backup.get(oldId); + int newId = mappings.remap(oldId); + + if (newId >= 0) { + this.registry.put(value, newId); + } + } + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + this.registry.osl$registries$clear(); + + for (int id : this.backup.osl$registries$idSet()) { + this.registry.put(this.backup.get(id), id); + } + } + + this.applied = false; + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java new file mode 100644 index 000000000..f6896b0bd --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,43 @@ +package net.ornithemc.osl.registries.impl; + +import net.minecraft.text.LiteralText; + +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.api.client.ClientPlayNetworking; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +public final class RegistriesEntrypoint implements ClientModInitializer { + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(Constants.OSL_REGISTRY_SYNC_CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesPacketSerializer.deserialize(buffer, RegistryMappingSource.REMOTE_SERVER); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.applyMappings(); + }); + } catch (RegistryMappingException e) { + RegistriesImpl.LOGGER.error("Unable to remap registries!", e); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.resetMappings(); + + if (context.networkHandler().getConnection().isConnected()) { + context.networkHandler().getConnection().disconnect(new LiteralText("Failed to remap registries: " + e.getMessage())); + } + }); + } + }); + ClientConnectionEvents.DISCONNECT.register(context -> { + if (!context.isServerLocal()) { + SyncedRegistriesImpl.undoMappings(); + } + }); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java new file mode 100644 index 000000000..77d1197bf --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java @@ -0,0 +1,58 @@ +package net.ornithemc.osl.registries.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 RegistriesMixinPlugin implements IMixinConfigPlugin { + + public static final boolean NEW_CRUDE_INCREMENTAL_INT_IDENTITY_HASH_MAP_IMPLEMENTATION = MinecraftVersion.resolve().compareTo("15w35a") >= 0; + public static final boolean ID_2_OBJECT_BI_MAP_EXISTS = MinecraftVersion.resolve().compareTo("15w36a") >= 0; + + @Override + public void onLoad(String mixinPackage) { + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if ("net.ornithemc.osl.registries.impl.mixin.common.CrudeIncrementalIntIdentityHashMapMixinNew".equals(mixinClassName)) { + return NEW_CRUDE_INCREMENTAL_INT_IDENTITY_HASH_MAP_IMPLEMENTATION; + } + if ("net.ornithemc.osl.registries.impl.mixin.common.CrudeIncrementalIntIdentityHashMapMixinOld".equals(mixinClassName)) { + return !NEW_CRUDE_INCREMENTAL_INT_IDENTITY_HASH_MAP_IMPLEMENTATION; + } + if ("net.ornithemc.osl.registries.impl.mixin.common.Id2ObjectBiMapMixin".equals(mixinClassName)) { + return ID_2_OBJECT_BI_MAP_EXISTS; + } + + 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/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java new file mode 100644 index 000000000..d7017be43 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java @@ -0,0 +1,16 @@ +package net.ornithemc.osl.registries.impl.access; + +public interface Clearable { + + static void clear(Object o) { + if (o instanceof Clearable) { + ((Clearable) o).osl$registries$clear(); + } else { + throw new IllegalArgumentException("not clearable: " + o); + } + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess.java new file mode 100644 index 000000000..d0437d3ac --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.access; + +import it.unimi.dsi.fastutil.ints.IntSet; + +public interface Id2ObjectBiMapAccess { + + default IntSet osl$registries$idSet() { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java new file mode 100644 index 000000000..fd39410ed --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java @@ -0,0 +1,18 @@ +package net.ornithemc.osl.registries.impl.access; + +public interface IdRegistryAccess { + + default void osl$registries$setCallback(RegisterCallback callback) { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } + + interface RegisterCallback { + + void valueRegistered(int id, Object key, Object value); + + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java new file mode 100644 index 000000000..ea596a58c --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java @@ -0,0 +1,11 @@ +package net.ornithemc.osl.registries.impl.access; + +import java.io.IOException; + +public interface WorldStorageAccess { + + void osl$registries$loadRegistryMappings() throws IOException; + + void osl$registries$saveRegistryMappings() throws IOException; + +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java new file mode 100644 index 000000000..16d16aa6b --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java @@ -0,0 +1,49 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import java.io.IOException; + +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.sugar.Local; + +import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.util.crash.CrashException; +import net.minecraft.util.crash.CrashReport; +import net.minecraft.world.storage.WorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(IntegratedServer.class) +public class IntegratedServerMixin { + + @Inject( + method = "loadWorld", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/storage/WorldStorage;loadData()Lnet/minecraft/world/WorldData;" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci, @Local WorldStorage storage) { + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$loadRegistryMappings(); + } catch (IOException e) { + throw new CrashException(CrashReport.of(e, "Exception initializing level")); + } + } + } + + @Inject( + method = "shutdown", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$unmapRegistries(CallbackInfo ci) { + SyncedRegistriesImpl.undoMappings(); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java new file mode 100644 index 000000000..f7de606ca --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,116 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.storage.AlphaWorldStorage; + +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesNbtSerializer; + +@Mixin(AlphaWorldStorage.class) +public class AlphaWorldStorageMixin implements WorldStorageAccess { + + @Shadow @Final + private String name; + + @Shadow + private File getDirectory() { return null; } + + @Override + public void osl$registries$loadRegistryMappings() throws IOException { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + + if (!this.readRegistryMappings(file, false)) { + file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + if (!this.readRegistryMappings(file, true)) { + RegistriesImpl.LOGGER.debug("no registry mappings read for '" + this.name + "'"); + } + } + } + + @Unique + private boolean readRegistryMappings(File file, boolean throwOnException) throws IOException { + if (file.exists()) { + try (InputStream is = new FileInputStream(file)) { + NbtCompound nbt = NbtIo.readCompressed(is); + + SyncedRegistriesNbtSerializer.deserialize(nbt, RegistryMappingSource.WORLD_SAVE); + SyncedRegistriesImpl.applyMappings(); + + return true; + } catch (IOException e) { + if (throwOnException) { + throw new IOException("Unable to read registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("error while reading registry mappings for '" + this.name + "'", e); + } + } catch (RegistryMappingException e) { + if (throwOnException) { + throw new IOException("Invalid registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("invalid registry mappings for '" + this.name + "'", e); + } + } + } + + return false; + } + + @Override + public void osl$registries$saveRegistryMappings() throws IOException { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + File tmp = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_tmp"); + File backup = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + this.writeRegistryMappings(file, tmp, backup); + } + + @Unique + private void writeRegistryMappings(File file, File newFile, File oldFile) throws IOException { + NbtCompound nbt = new NbtCompound(); + + try { + SyncedRegistriesNbtSerializer.serialize(nbt); + + try (OutputStream os = new FileOutputStream(newFile)) { + NbtIo.writeCompressed(nbt, os); + } + + if (oldFile.exists()) { + oldFile.delete(); + } + + file.renameTo(oldFile); + if (file.exists()) { + file.delete(); + } + + newFile.renameTo(file); + if (newFile.exists()) { + newFile.delete(); + } + } catch (IOException e) { + RegistriesImpl.LOGGER.warn("error while writing registry mappings for '" + this.name + "'", e); + } + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java new file mode 100644 index 000000000..b27f392a5 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; + +import net.minecraft.Bootstrap; + +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(Bootstrap.class) +public class BootstrapMixin { + + @Shadow + private static boolean initialized; + + @WrapMethod(method = "init()V") + private static void osl$registries$initAndLockRegistries(Operation op) { + boolean wasInitialized = initialized; + + // we could skip the call if initialized is already true + // but let's not mess with the bootstrap too much, eh + op.call(); + + if (!wasInitialized) { + RegistriesImpl.init(); + SyncedRegistriesImpl.init(); + } + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixinNew.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixinNew.java new file mode 100644 index 000000000..e91c8bc6c --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixinNew.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Arrays; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; + +import net.ornithemc.osl.registries.impl.access.Clearable; + +@Mixin(CrudeIncrementalIntIdentityHashMap.class) +public class CrudeIncrementalIntIdentityHashMapMixinNew implements Clearable { + + @Shadow + private Object[] keys; + @Shadow + private Object[] byId; + + @Shadow + private int nextId; + @Shadow + private int size; + + @Override + public void osl$registries$clear() { + Arrays.fill(this.keys, null); + Arrays.fill(this.byId, null); + + this.nextId = 0; + this.size = 0; + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixinOld.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixinOld.java new file mode 100644 index 000000000..b00ca34bd --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixinOld.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.IdentityHashMap; +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; + +import net.ornithemc.osl.registries.impl.access.Clearable; + +@Mixin(CrudeIncrementalIntIdentityHashMap.class) +public class CrudeIncrementalIntIdentityHashMapMixinOld implements Clearable { + + @Shadow + private IdentityHashMap f_29800171; // ids + @Shadow + private List f_87828088; // values + + @Override + public void osl$registries$clear() { + this.f_29800171.clear(); + this.f_87828088.clear(); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java new file mode 100644 index 000000000..cc07e9aa0 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.util.registry.DefaultedIdRegistry; + +@Mixin(DefaultedIdRegistry.class) +public interface DefaultedIdRegistryAccess { + + @Accessor("defaultKey") + Object accessDefaultKey(); + +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java new file mode 100644 index 000000000..aec9b5cf6 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java @@ -0,0 +1,54 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.IdentityHashMap; +import java.util.List; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; + +import net.minecraft.util.Id2ObjectBiMap; + +import net.ornithemc.osl.registries.impl.access.Clearable; +import net.ornithemc.osl.registries.impl.access.Id2ObjectBiMapAccess; + +@Mixin(Id2ObjectBiMap.class) +public class Id2ObjectBiMapMixin implements Id2ObjectBiMapAccess, Clearable { + + @Shadow @Final + private List values; + @Shadow @Final + private IdentityHashMap ids; + + @Unique + private final IntSet idSet = new IntOpenHashSet(); + + @Inject( + method = "put(Ljava/lang/Object;I)V", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$put(T value, int id, CallbackInfo ci) { + this.idSet.add(id); + } + + @Override + public IntSet osl$registries$idSet() { + return this.idSet; + } + + @Override + public void osl$registries$clear() { + this.values.clear(); + this.ids.clear(); + this.idSet.clear(); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java new file mode 100644 index 000000000..c6d703bc1 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java @@ -0,0 +1,80 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Map; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +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.util.CrudeIncrementalIntIdentityHashMap; +import net.minecraft.util.registry.IdRegistry; +import net.minecraft.util.registry.MappedRegistry; + +import net.ornithemc.osl.registries.impl.access.Clearable; +import net.ornithemc.osl.registries.impl.access.IdRegistryAccess; + +@Mixin(IdRegistry.class) +public class IdRegistryMixin extends MappedRegistry implements IdRegistryAccess, Clearable { + + @Shadow @Final + private CrudeIncrementalIntIdentityHashMap ids; + @Shadow @Final + private Map keys; + + @Unique + private RegisterCallback callback; + @Unique + private int nextId; + + @Shadow + private void register(int id, K key, V value) { } + + @Redirect( + method = "register", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/util/registry/IdRegistry;put(Ljava/lang/Object;Ljava/lang/Object;)V" + ) + ) + private void osl$registries$replaceThisPutWithSuperPut(IdRegistry self, K key, V value) { + super.put(key, value); + } + + @Inject( + method = "register", + at = @At( + value = "RETURN" + ) + ) + private void osl$registries$register(int id, K key, V value, CallbackInfo ci) { + this.nextId = Math.max(this.nextId, id + 1); + + if (this.callback != null) { + this.callback.valueRegistered(id, key, value); + } + } + + @Override + public void put(K key, V value) { + this.register(this.nextId, key, value); + } + + @Override + public void osl$registries$setCallback(RegisterCallback callback) { + this.callback = callback; + } + + @Override + public void osl$registries$clear() { + this.entries.clear(); + this.keys.clear(); + Clearable.clear(this.ids); + + this.nextId = 0; + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java new file mode 100644 index 000000000..61a318c15 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java @@ -0,0 +1,61 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.IOException; + +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.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.crash.CrashException; +import net.minecraft.util.crash.CrashReport; +import net.minecraft.world.storage.WorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + + @Inject( + method = "loadWorld", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/storage/WorldStorage;loadData()Lnet/minecraft/world/WorldData;" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci, @Local WorldStorage storage) { + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$loadRegistryMappings(); + } catch (IOException e) { + throw new CrashException(CrashReport.of(e, "Exception initializing level")); + } + } + } + + @Inject( + method = "saveWorlds", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(CallbackInfo ci) { + MinecraftServer server = (MinecraftServer) (Object) this; + + ServerWorld overworld = server.worlds[0]; + WorldStorage storage = overworld.getStorage(); + + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$saveRegistryMappings(); + } catch (IOException e) { + RegistriesImpl.LOGGER.error("Exception saving level", e); + } + } + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java new file mode 100644 index 000000000..37a827c2d --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.registries.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 com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerPlayNetworking; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final + private MinecraftServer server; + + @Inject( + method = "onLogin", + at = @At( + value = "NEW", + target = "net/minecraft/network/packet/s2c/play/LoginS2CPacket" + ) + ) + private void osl$idsync$syncRegistries(CallbackInfo ci, @Local ServerPlayerEntity player) { + if (this.server.isDedicated() || !this.server.getUsername().equals(player.getName())) { + ServerPlayNetworking.sendNoCheck(player, Constants.OSL_REGISTRY_SYNC_CHANNEL, SyncedRegistriesPacketSerializer::serialize); + } + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java new file mode 100644 index 000000000..70bd45ea0 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java @@ -0,0 +1,30 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.function.Supplier; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.DefaultedIdRegistry; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public final class VanillaRegistries { + + public static Registry registerSimple(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return registerSimple(key, registry, () -> null); + } + + public static Registry registerSimple(ResourceKey> key, net.minecraft.util.registry.Registry registry, Supplier bootstrap) { + return RegistriesImpl.register(key, WrappedIdRegistry.of(key, (IdRegistry) registry), bootstrap::get); + } + + public static DefaultedRegistry registerDefaulted(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return registerDefaulted(key, registry, () -> null); + } + + public static DefaultedRegistry registerDefaulted(ResourceKey> key, net.minecraft.util.registry.Registry registry, Supplier bootstrap) { + return RegistriesImpl.register(key, WrappedDefaultedIdRegistry.of(key, (DefaultedIdRegistry) registry), bootstrap::get); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java new file mode 100644 index 000000000..ae769c9c0 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.DefaultedIdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.impl.mixin.common.DefaultedIdRegistryAccess; + +public class WrappedDefaultedIdRegistry extends WrappedIdRegistry implements DefaultedRegistry { + + public static WrappedDefaultedIdRegistry of(ResourceKey> key, DefaultedIdRegistry registry) { + return new WrappedDefaultedIdRegistry<>(key.identifier(), registry); + } + + private WrappedDefaultedIdRegistry(NamespacedIdentifier identifier, DefaultedIdRegistry registry) { + super(identifier, registry); + } + + @Override + public NamespacedIdentifier getDefaultIdentifier() { + return this.serializeKey((Identifier) ((DefaultedIdRegistryAccess) this.registry).accessDefaultKey()); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java new file mode 100644 index 000000000..c16b91755 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java @@ -0,0 +1,131 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.Iterator; +import java.util.Set; +import java.util.stream.Collectors; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.ResourceKeys; + +public class WrappedIdRegistry implements ClearableRegistry { + + public static WrappedIdRegistry of(ResourceKey> key, IdRegistry registry) { + return new WrappedIdRegistry<>(key.identifier(), registry); + } + + final NamespacedIdentifier identifier; + final IdRegistry registry; + + private int nextId; + private boolean frozen; + + WrappedIdRegistry(NamespacedIdentifier identifier, IdRegistry registry) { + this.identifier = identifier; + this.registry = registry; + + this.registry.osl$registries$setCallback(this::valueRegistered); + } + + NamespacedIdentifier serializeKey(Identifier key) { + return key; + } + + Identifier deserializeKey(NamespacedIdentifier identifier) { + return identifier == null ? null : (identifier instanceof Identifier ? (Identifier) identifier : new Identifier(identifier.namespace(), identifier.identifier())); + } + + ResourceKey resourceKey(NamespacedIdentifier identifier) { + return identifier == null ? null : ResourceKeys.from(this.identifier, identifier); + } + + private void valueRegistered(int id, Object key, Object value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + + this.nextId = Math.max(this.nextId, id + 1); + } + + @Override + public V register(ResourceKey key, V value) { + return this.register(this.nextId, key, value); + } + + @Override + public V register(int id, ResourceKey key, V value) { + this.registry.register(id, this.deserializeKey(key.identifier()), value); + return value; + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } + + @Override + public T get(int id) { + return this.registry.get(id); + } + + @Override + public T get(ResourceKey key) { + return this.registry.get(this.deserializeKey(key.identifier())); + } + + @Override + public T get(NamespacedIdentifier identifier) { + return this.registry.get(this.deserializeKey(identifier)); + } + + @Override + public int getId(T value) { + return this.registry.getId(value); + } + + @Override + public ResourceKey getKey(T value) { + return this.resourceKey(this.serializeKey(this.registry.getKey(value))); + } + + @Override + public NamespacedIdentifier getIdentifier(T value) { + return this.serializeKey(this.registry.getKey(value)); + } + + @Override + public Set> keySet() { + return this.registry.keySet().stream().map(this::serializeKey).map(this::resourceKey).collect(Collectors.toSet()); + } + + @Override + public Set identifierSet() { + return this.registry.keySet().stream().map(this::serializeKey).collect(Collectors.toSet()); + } + + @Override + public Iterator iterator() { + return this.registry.iterator(); + } + + @Override + public Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public void clear() { + this.registry.osl$registries$clear(); + + this.nextId = 0; + this.frozen = false; + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java new file mode 100644 index 000000000..b2b48ca34 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java @@ -0,0 +1,78 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.minecraft.nbt.NbtCompound; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesNbtSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(NbtCompound nbt) throws IOException { + NbtCompound registriesNbt = new NbtCompound(); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt, SyncedRegistriesNbtSerializer::serialize); + registriesNbt.put(identifier.toString(), mappingsNbt); + } + + nbt.putInt(Constants.FORMAT_NBT_KEY, Constants.REGISTRY_MAPPINGS_FORMAT); + nbt.put(Constants.REGISTRIES_NBT_KEY, registriesNbt); + } + + public static void deserialize(NbtCompound nbt, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = nbt.getInt(Constants.FORMAT_NBT_KEY); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + NbtCompound registriesNbt = nbt.getCompound(Constants.REGISTRIES_NBT_KEY); + + for (String key : registriesNbt.getKeys()) { + NbtCompound mappingsNbt = registriesNbt.getCompound(key); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(key); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(mappingsNbt, SyncedRegistriesNbtSerializer::deserialize, source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(NbtCompound nbt, Object2IntMap mappings) throws IOException { + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } + + public static void deserialize(NbtCompound nbt, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + for (String key : nbt.getKeys()) { + mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java new file mode 100644 index 000000000..d21165816 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java @@ -0,0 +1,81 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesPacketSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(Constants.REGISTRY_MAPPINGS_FORMAT); + buffer.writeVarInt(REGISTRIES.keySet().size()); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer, SyncedRegistriesPacketSerializer::serialize); + } + } + + public static void deserialize(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(buffer, SyncedRegistriesPacketSerializer::deserialize, source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(PacketBuffer buffer, Object2IntMap mappings) throws IOException { + buffer.writeVarInt(mappings.size()); + + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public static void deserialize(PacketBuffer buffer, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + mappings.put(identifier, id); + } + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/fabric.mod.json b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..b5628aeb6 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/fabric.mod.json @@ -0,0 +1,37 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc14w27a-mc17w46a", + "environment": "*", + "entrypoints": { + "client-init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ] + }, + "mixins": [ + "osl.registries.mixins.json" + ], + "accessWidener": "osl.registries.classtweaker", + "depends": { + "fabricloader": "\u003e\u003d0.18.0", + "minecraft": "\u003e\u003d1.8-alpha.14.27.a \u003c\u003d1.13-alpha.17.46.a", + "osl-core": "\u003e\u003d0.8.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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0" + }, + "name": "OSL Registries", + "description": "Registries API and numerical ID synchronization.", + "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/registries/registries-mc14w27a-mc17w46a/src/main/resources/osl.registries.classtweaker b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/osl.registries.classtweaker new file mode 100644 index 000000000..cea48538c --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/osl.registries.classtweaker @@ -0,0 +1,4 @@ +classTweaker v1 named + +inject-interface net/minecraft/util/Id2ObjectBiMap net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess +inject-interface net/minecraft/util/registry/IdRegistry net/ornithemc/osl/registries/impl/access/IdRegistryAccess \ No newline at end of file diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/osl.registries.mixins.json b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/osl.registries.mixins.json new file mode 100644 index 000000000..df2415d06 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,26 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "plugin": "net.ornithemc.osl.registries.impl.RegistriesMixinPlugin", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.BootstrapMixin", + "common.CrudeIncrementalIntIdentityHashMapMixinNew", + "common.CrudeIncrementalIntIdentityHashMapMixinOld", + "common.DefaultedIdRegistryAccess", + "common.Id2ObjectBiMapMixin", + "common.IdRegistryMixin", + "common.MinecraftServerMixin", + "common.PlayerManagerMixin" + ], + "client": [ + "client.IntegratedServerMixin" + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/build.gradle b/libraries/registries/registries-mc17w47a-mc18w31a/build.gradle new file mode 100644 index 000000000..0a350fdb3 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/build.gradle @@ -0,0 +1 @@ +setUpModule(project) diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/gradle.properties b/libraries/registries/registries-mc17w47a-mc18w31a/gradle.properties new file mode 100644 index 000000000..214f5d68e --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/gradle.properties @@ -0,0 +1,5 @@ +min_mc_version = 17w47a +max_mc_version = 18w31a +minecraft_dependency = >=1.13-alpha.17.47.a <=1.13.1-alpha.18.31.a + +minecraft_version = 1.13 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 new file mode 100644 index 000000000..87d5b78ad --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; + +/** + * Utility class containing commonly used registry keys (i.e. @linkplain + * ResourceKey resource keys} for registries), as well as factory methods + * for creating registry keys. + */ +public final class RegistryKeys { + + public static final ResourceKey> BLOCK = from("block"); + public static final ResourceKey> ITEM = from("item"); + + /** + * Constructs a registry key with the default namespace and the given identifier. + * + * @param the value type of the registry. + * @param identifier the identifier of the registry. + * @return the constructed registry key. + */ + public static ResourceKey> from(String identifier) { + return from(NamespacedIdentifiers.from(identifier)); + } + + /** + * Constructs a registry key with the given namespaced identifier. + * + * @param the value type of the registry. + * @param identifier the namespaced identifier of the registry. + * @return the constructed registry key. + */ + public static ResourceKey> from(NamespacedIdentifier identifier) { + return ResourceKeys.from(identifier); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java new file mode 100644 index 000000000..544daace9 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java @@ -0,0 +1,67 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import net.minecraft.util.Id2ObjectBiMap; + +/** + * An {@linkplain IdMapper} implementation for {@linkplain Id2ObjectBiMap}s + * where IDs are used as keys to the map. The values are moved from the old key + * (the old ID) to the new key (the new ID) within the same map. {@code null} is + * used as the default or "empty" value. + */ +public class Id2ObjectBiMapMapper implements IdMapper { + + public static Id2ObjectBiMapMapper of(Id2ObjectBiMap registry) { + return new Id2ObjectBiMapMapper(registry); + } + + private final Id2ObjectBiMap registry; + private final Id2ObjectBiMap backup; + + private boolean applied; + + @SuppressWarnings("unchecked") + private Id2ObjectBiMapMapper(Id2ObjectBiMap registry) { + this.registry = (Id2ObjectBiMap) registry; + this.backup = new Id2ObjectBiMap<>(registry.size()); + } + + /* + * unlike Registry, Id2ObjectBiMap allows duplicate values + * thus iterating over all values will not give you all id-value pairs! + */ + + @Override + public void apply(RegistryMappings mappings) { + this.backup.osl$registries$clear(); + + for (int id : this.registry.osl$registries$idSet()) { + this.backup.put(this.registry.get(id), id); + } + + this.registry.osl$registries$clear(); + + for (int oldId : this.backup.osl$registries$idSet()) { + Object value = this.backup.get(oldId); + int newId = mappings.remap(oldId); + + if (newId >= 0) { + this.registry.put(value, newId); + } + } + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + this.registry.osl$registries$clear(); + + for (int id : this.backup.osl$registries$idSet()) { + this.registry.put(this.backup.get(id), id); + } + } + + this.applied = false; + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java new file mode 100644 index 000000000..f6896b0bd --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,43 @@ +package net.ornithemc.osl.registries.impl; + +import net.minecraft.text.LiteralText; + +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.api.client.ClientPlayNetworking; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +public final class RegistriesEntrypoint implements ClientModInitializer { + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(Constants.OSL_REGISTRY_SYNC_CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesPacketSerializer.deserialize(buffer, RegistryMappingSource.REMOTE_SERVER); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.applyMappings(); + }); + } catch (RegistryMappingException e) { + RegistriesImpl.LOGGER.error("Unable to remap registries!", e); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.resetMappings(); + + if (context.networkHandler().getConnection().isConnected()) { + context.networkHandler().getConnection().disconnect(new LiteralText("Failed to remap registries: " + e.getMessage())); + } + }); + } + }); + ClientConnectionEvents.DISCONNECT.register(context -> { + if (!context.isServerLocal()) { + SyncedRegistriesImpl.undoMappings(); + } + }); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java new file mode 100644 index 000000000..d7017be43 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java @@ -0,0 +1,16 @@ +package net.ornithemc.osl.registries.impl.access; + +public interface Clearable { + + static void clear(Object o) { + if (o instanceof Clearable) { + ((Clearable) o).osl$registries$clear(); + } else { + throw new IllegalArgumentException("not clearable: " + o); + } + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess.java new file mode 100644 index 000000000..d0437d3ac --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.access; + +import it.unimi.dsi.fastutil.ints.IntSet; + +public interface Id2ObjectBiMapAccess { + + default IntSet osl$registries$idSet() { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java new file mode 100644 index 000000000..fd39410ed --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java @@ -0,0 +1,18 @@ +package net.ornithemc.osl.registries.impl.access; + +public interface IdRegistryAccess { + + default void osl$registries$setCallback(RegisterCallback callback) { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } + + interface RegisterCallback { + + void valueRegistered(int id, Object key, Object value); + + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java new file mode 100644 index 000000000..ea596a58c --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java @@ -0,0 +1,11 @@ +package net.ornithemc.osl.registries.impl.access; + +import java.io.IOException; + +public interface WorldStorageAccess { + + void osl$registries$loadRegistryMappings() throws IOException; + + void osl$registries$saveRegistryMappings() throws IOException; + +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java new file mode 100644 index 000000000..16d16aa6b --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java @@ -0,0 +1,49 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import java.io.IOException; + +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.sugar.Local; + +import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.util.crash.CrashException; +import net.minecraft.util.crash.CrashReport; +import net.minecraft.world.storage.WorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(IntegratedServer.class) +public class IntegratedServerMixin { + + @Inject( + method = "loadWorld", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/storage/WorldStorage;loadData()Lnet/minecraft/world/WorldData;" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci, @Local WorldStorage storage) { + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$loadRegistryMappings(); + } catch (IOException e) { + throw new CrashException(CrashReport.of(e, "Exception initializing level")); + } + } + } + + @Inject( + method = "shutdown", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$unmapRegistries(CallbackInfo ci) { + SyncedRegistriesImpl.undoMappings(); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java new file mode 100644 index 000000000..f7de606ca --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,116 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.storage.AlphaWorldStorage; + +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesNbtSerializer; + +@Mixin(AlphaWorldStorage.class) +public class AlphaWorldStorageMixin implements WorldStorageAccess { + + @Shadow @Final + private String name; + + @Shadow + private File getDirectory() { return null; } + + @Override + public void osl$registries$loadRegistryMappings() throws IOException { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + + if (!this.readRegistryMappings(file, false)) { + file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + if (!this.readRegistryMappings(file, true)) { + RegistriesImpl.LOGGER.debug("no registry mappings read for '" + this.name + "'"); + } + } + } + + @Unique + private boolean readRegistryMappings(File file, boolean throwOnException) throws IOException { + if (file.exists()) { + try (InputStream is = new FileInputStream(file)) { + NbtCompound nbt = NbtIo.readCompressed(is); + + SyncedRegistriesNbtSerializer.deserialize(nbt, RegistryMappingSource.WORLD_SAVE); + SyncedRegistriesImpl.applyMappings(); + + return true; + } catch (IOException e) { + if (throwOnException) { + throw new IOException("Unable to read registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("error while reading registry mappings for '" + this.name + "'", e); + } + } catch (RegistryMappingException e) { + if (throwOnException) { + throw new IOException("Invalid registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("invalid registry mappings for '" + this.name + "'", e); + } + } + } + + return false; + } + + @Override + public void osl$registries$saveRegistryMappings() throws IOException { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + File tmp = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_tmp"); + File backup = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + this.writeRegistryMappings(file, tmp, backup); + } + + @Unique + private void writeRegistryMappings(File file, File newFile, File oldFile) throws IOException { + NbtCompound nbt = new NbtCompound(); + + try { + SyncedRegistriesNbtSerializer.serialize(nbt); + + try (OutputStream os = new FileOutputStream(newFile)) { + NbtIo.writeCompressed(nbt, os); + } + + if (oldFile.exists()) { + oldFile.delete(); + } + + file.renameTo(oldFile); + if (file.exists()) { + file.delete(); + } + + newFile.renameTo(file); + if (newFile.exists()) { + newFile.delete(); + } + } catch (IOException e) { + RegistriesImpl.LOGGER.warn("error while writing registry mappings for '" + this.name + "'", e); + } + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java new file mode 100644 index 000000000..b27f392a5 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; + +import net.minecraft.Bootstrap; + +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(Bootstrap.class) +public class BootstrapMixin { + + @Shadow + private static boolean initialized; + + @WrapMethod(method = "init()V") + private static void osl$registries$initAndLockRegistries(Operation op) { + boolean wasInitialized = initialized; + + // we could skip the call if initialized is already true + // but let's not mess with the bootstrap too much, eh + op.call(); + + if (!wasInitialized) { + RegistriesImpl.init(); + SyncedRegistriesImpl.init(); + } + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java new file mode 100644 index 000000000..773df9d09 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Arrays; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; + +import net.ornithemc.osl.registries.impl.access.Clearable; + +@Mixin(CrudeIncrementalIntIdentityHashMap.class) +public class CrudeIncrementalIntIdentityHashMapMixin implements Clearable { + + @Shadow + private Object[] keys; + @Shadow + private Object[] byId; + + @Shadow + private int nextId; + @Shadow + private int size; + + @Override + public void osl$registries$clear() { + Arrays.fill(this.keys, null); + Arrays.fill(this.byId, null); + + this.nextId = 0; + this.size = 0; + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java new file mode 100644 index 000000000..cc07e9aa0 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.util.registry.DefaultedIdRegistry; + +@Mixin(DefaultedIdRegistry.class) +public interface DefaultedIdRegistryAccess { + + @Accessor("defaultKey") + Object accessDefaultKey(); + +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java new file mode 100644 index 000000000..3a3ce1078 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java @@ -0,0 +1,59 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.IdentityHashMap; +import java.util.List; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; + +import net.minecraft.util.Id2ObjectBiMap; + +import net.ornithemc.osl.registries.impl.access.Clearable; +import net.ornithemc.osl.registries.impl.access.Id2ObjectBiMapAccess; + +@Mixin(Id2ObjectBiMap.class) +public class Id2ObjectBiMapMixin implements Id2ObjectBiMapAccess, Clearable { + + @Shadow @Final + private List values; + @Shadow @Final + private IdentityHashMap ids; + + @Shadow + private int nextId; + + @Unique + private final IntSet idSet = new IntOpenHashSet(); + + @Inject( + method = "put(Ljava/lang/Object;I)V", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$put(T value, int id, CallbackInfo ci) { + this.idSet.add(id); + } + + @Override + public IntSet osl$registries$idSet() { + return this.idSet; + } + + @Override + public void osl$registries$clear() { + this.values.clear(); + this.ids.clear(); + this.idSet.clear(); + + this.nextId = 0; + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java new file mode 100644 index 000000000..a070f7196 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java @@ -0,0 +1,54 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Map; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +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.CrudeIncrementalIntIdentityHashMap; +import net.minecraft.util.registry.IdRegistry; +import net.minecraft.util.registry.MappedRegistry; + +import net.ornithemc.osl.registries.impl.access.Clearable; +import net.ornithemc.osl.registries.impl.access.IdRegistryAccess; + +@Mixin(IdRegistry.class) +public class IdRegistryMixin extends MappedRegistry implements IdRegistryAccess, Clearable { + + @Shadow @Final + private CrudeIncrementalIntIdentityHashMap ids; + @Shadow @Final + private Map keys; + + @Unique + private RegisterCallback callback; + + @Inject( + method = "register", + at = @At( + value = "RETURN" + ) + ) + private void osl$registries$register(int id, K key, V value, CallbackInfo ci) { + if (this.callback != null) { + this.callback.valueRegistered(id, key, value); + } + } + + @Override + public void osl$registries$setCallback(RegisterCallback callback) { + this.callback = callback; + } + + @Override + public void osl$registries$clear() { + this.entries.clear(); + this.keys.clear(); + Clearable.clear(this.ids); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java new file mode 100644 index 000000000..61a318c15 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java @@ -0,0 +1,61 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.IOException; + +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.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.crash.CrashException; +import net.minecraft.util.crash.CrashReport; +import net.minecraft.world.storage.WorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + + @Inject( + method = "loadWorld", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/storage/WorldStorage;loadData()Lnet/minecraft/world/WorldData;" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci, @Local WorldStorage storage) { + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$loadRegistryMappings(); + } catch (IOException e) { + throw new CrashException(CrashReport.of(e, "Exception initializing level")); + } + } + } + + @Inject( + method = "saveWorlds", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(CallbackInfo ci) { + MinecraftServer server = (MinecraftServer) (Object) this; + + ServerWorld overworld = server.worlds[0]; + WorldStorage storage = overworld.getStorage(); + + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$saveRegistryMappings(); + } catch (IOException e) { + RegistriesImpl.LOGGER.error("Exception saving level", e); + } + } + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java new file mode 100644 index 000000000..01174aa6b --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.registries.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 com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerPlayNetworking; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final + private MinecraftServer server; + + @Inject( + method = "onLogin", + at = @At( + value = "NEW", + target = "net/minecraft/network/packet/s2c/play/LoginS2CPacket" + ) + ) + private void osl$idsync$syncRegistries(CallbackInfo ci, @Local ServerPlayerEntity player) { + if (this.server.isDedicated() || !this.server.getUsername().equals(player.getGameProfile().getName())) { + ServerPlayNetworking.sendNoCheck(player, Constants.OSL_REGISTRY_SYNC_CHANNEL, SyncedRegistriesPacketSerializer::serialize); + } + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java new file mode 100644 index 000000000..70bd45ea0 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java @@ -0,0 +1,30 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.function.Supplier; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.DefaultedIdRegistry; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public final class VanillaRegistries { + + public static Registry registerSimple(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return registerSimple(key, registry, () -> null); + } + + public static Registry registerSimple(ResourceKey> key, net.minecraft.util.registry.Registry registry, Supplier bootstrap) { + return RegistriesImpl.register(key, WrappedIdRegistry.of(key, (IdRegistry) registry), bootstrap::get); + } + + public static DefaultedRegistry registerDefaulted(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return registerDefaulted(key, registry, () -> null); + } + + public static DefaultedRegistry registerDefaulted(ResourceKey> key, net.minecraft.util.registry.Registry registry, Supplier bootstrap) { + return RegistriesImpl.register(key, WrappedDefaultedIdRegistry.of(key, (DefaultedIdRegistry) registry), bootstrap::get); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java new file mode 100644 index 000000000..ae769c9c0 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.DefaultedIdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.impl.mixin.common.DefaultedIdRegistryAccess; + +public class WrappedDefaultedIdRegistry extends WrappedIdRegistry implements DefaultedRegistry { + + public static WrappedDefaultedIdRegistry of(ResourceKey> key, DefaultedIdRegistry registry) { + return new WrappedDefaultedIdRegistry<>(key.identifier(), registry); + } + + private WrappedDefaultedIdRegistry(NamespacedIdentifier identifier, DefaultedIdRegistry registry) { + super(identifier, registry); + } + + @Override + public NamespacedIdentifier getDefaultIdentifier() { + return this.serializeKey((Identifier) ((DefaultedIdRegistryAccess) this.registry).accessDefaultKey()); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java new file mode 100644 index 000000000..96dea86ae --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java @@ -0,0 +1,131 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.Iterator; +import java.util.Set; +import java.util.stream.Collectors; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.ResourceKeys; + +public class WrappedIdRegistry implements ClearableRegistry { + + public static WrappedIdRegistry of(ResourceKey> key, IdRegistry registry) { + return new WrappedIdRegistry<>(key.identifier(), registry); + } + + final NamespacedIdentifier identifier; + final IdRegistry registry; + + private int nextId; + private boolean frozen; + + WrappedIdRegistry(NamespacedIdentifier identifier, IdRegistry registry) { + this.identifier = identifier; + this.registry = registry; + + this.registry.osl$registries$setCallback(this::valueRegistered); + } + + NamespacedIdentifier serializeKey(Identifier key) { + return key; + } + + Identifier deserializeKey(NamespacedIdentifier identifier) { + return identifier == null ? null : (identifier instanceof Identifier ? (Identifier) identifier : new Identifier(identifier.namespace(), identifier.identifier())); + } + + ResourceKey resourceKey(NamespacedIdentifier identifier) { + return identifier == null ? null : ResourceKeys.from(this.identifier, identifier); + } + + private void valueRegistered(int id, Object key, Object value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + + this.nextId = Math.max(this.nextId, id + 1); + } + + @Override + public V register(ResourceKey key, V value) { + return this.register(this.nextId, key, value); + } + + @Override + public V register(int id, ResourceKey key, V value) { + this.registry.register(id, this.deserializeKey(key.identifier()), value); + return value; + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } + + @Override + public T get(int id) { + return this.registry.get(id); + } + + @Override + public T get(ResourceKey key) { + return this.registry.get(this.deserializeKey(key.identifier())); + } + + @Override + public T get(NamespacedIdentifier identifier) { + return this.registry.get(this.deserializeKey(identifier)); + } + + @Override + public int getId(T value) { + return this.registry.getId(value); + } + + @Override + public ResourceKey getKey(T value) { + return this.resourceKey(this.serializeKey(this.registry.getKey(value))); + } + + @Override + public NamespacedIdentifier getIdentifier(T value) { + return this.serializeKey(this.registry.getKey(value)); + } + + @Override + public Set> keySet() { + return this.registry.entrySet().stream().map(this::serializeKey).map(this::resourceKey).collect(Collectors.toSet()); + } + + @Override + public Set identifierSet() { + return this.registry.entrySet().stream().map(this::serializeKey).collect(Collectors.toSet()); + } + + @Override + public Iterator iterator() { + return this.registry.iterator(); + } + + @Override + public Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public void clear() { + this.registry.osl$registries$clear(); + + this.nextId = 0; + this.frozen = false; + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java new file mode 100644 index 000000000..b2b48ca34 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java @@ -0,0 +1,78 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.minecraft.nbt.NbtCompound; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesNbtSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(NbtCompound nbt) throws IOException { + NbtCompound registriesNbt = new NbtCompound(); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt, SyncedRegistriesNbtSerializer::serialize); + registriesNbt.put(identifier.toString(), mappingsNbt); + } + + nbt.putInt(Constants.FORMAT_NBT_KEY, Constants.REGISTRY_MAPPINGS_FORMAT); + nbt.put(Constants.REGISTRIES_NBT_KEY, registriesNbt); + } + + public static void deserialize(NbtCompound nbt, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = nbt.getInt(Constants.FORMAT_NBT_KEY); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + NbtCompound registriesNbt = nbt.getCompound(Constants.REGISTRIES_NBT_KEY); + + for (String key : registriesNbt.getKeys()) { + NbtCompound mappingsNbt = registriesNbt.getCompound(key); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(key); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(mappingsNbt, SyncedRegistriesNbtSerializer::deserialize, source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(NbtCompound nbt, Object2IntMap mappings) throws IOException { + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } + + public static void deserialize(NbtCompound nbt, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + for (String key : nbt.getKeys()) { + mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java new file mode 100644 index 000000000..d21165816 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java @@ -0,0 +1,81 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesPacketSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(Constants.REGISTRY_MAPPINGS_FORMAT); + buffer.writeVarInt(REGISTRIES.keySet().size()); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer, SyncedRegistriesPacketSerializer::serialize); + } + } + + public static void deserialize(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(buffer, SyncedRegistriesPacketSerializer::deserialize, source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(PacketBuffer buffer, Object2IntMap mappings) throws IOException { + buffer.writeVarInt(mappings.size()); + + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public static void deserialize(PacketBuffer buffer, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + mappings.put(identifier, id); + } + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/fabric.mod.json b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..712d82669 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/fabric.mod.json @@ -0,0 +1,37 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc17w47a-mc18w31a", + "environment": "*", + "entrypoints": { + "client-init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ] + }, + "mixins": [ + "osl.registries.mixins.json" + ], + "accessWidener": "osl.registries.classtweaker", + "depends": { + "fabricloader": "\u003e\u003d0.18.0", + "minecraft": "\u003e\u003d1.13-alpha.17.47.a \u003c\u003d1.13.1-alpha.18.31.a", + "osl-core": "\u003e\u003d0.8.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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0" + }, + "name": "OSL Registries", + "description": "Registries API and numerical ID synchronization.", + "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/registries/registries-mc17w47a-mc18w31a/src/main/resources/osl.registries.classtweaker b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/osl.registries.classtweaker new file mode 100644 index 000000000..cea48538c --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/osl.registries.classtweaker @@ -0,0 +1,4 @@ +classTweaker v1 named + +inject-interface net/minecraft/util/Id2ObjectBiMap net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess +inject-interface net/minecraft/util/registry/IdRegistry net/ornithemc/osl/registries/impl/access/IdRegistryAccess \ No newline at end of file diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/osl.registries.mixins.json b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/osl.registries.mixins.json new file mode 100644 index 000000000..60e06d4c1 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,24 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.BootstrapMixin", + "common.CrudeIncrementalIntIdentityHashMapMixin", + "common.DefaultedIdRegistryAccess", + "common.Id2ObjectBiMapMixin", + "common.IdRegistryMixin", + "common.MinecraftServerMixin", + "common.PlayerManagerMixin" + ], + "client": [ + "client.IntegratedServerMixin" + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/build.gradle b/libraries/registries/registries-mc18w32a-mc1.13.2/build.gradle new file mode 100644 index 000000000..0a350fdb3 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/build.gradle @@ -0,0 +1 @@ +setUpModule(project) diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/gradle.properties b/libraries/registries/registries-mc18w32a-mc1.13.2/gradle.properties new file mode 100644 index 000000000..4c9c26193 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/gradle.properties @@ -0,0 +1,5 @@ +min_mc_version = 18w32a +max_mc_version = 1.13.2 +minecraft_dependency = >=1.13.1-alpha.18.32.a <=1.13.2 + +minecraft_version = 1.13.2 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 new file mode 100644 index 000000000..87d5b78ad --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; + +/** + * Utility class containing commonly used registry keys (i.e. @linkplain + * ResourceKey resource keys} for registries), as well as factory methods + * for creating registry keys. + */ +public final class RegistryKeys { + + public static final ResourceKey> BLOCK = from("block"); + public static final ResourceKey> ITEM = from("item"); + + /** + * Constructs a registry key with the default namespace and the given identifier. + * + * @param the value type of the registry. + * @param identifier the identifier of the registry. + * @return the constructed registry key. + */ + public static ResourceKey> from(String identifier) { + return from(NamespacedIdentifiers.from(identifier)); + } + + /** + * Constructs a registry key with the given namespaced identifier. + * + * @param the value type of the registry. + * @param identifier the namespaced identifier of the registry. + * @return the constructed registry key. + */ + public static ResourceKey> from(NamespacedIdentifier identifier) { + return ResourceKeys.from(identifier); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java new file mode 100644 index 000000000..544daace9 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java @@ -0,0 +1,67 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import net.minecraft.util.Id2ObjectBiMap; + +/** + * An {@linkplain IdMapper} implementation for {@linkplain Id2ObjectBiMap}s + * where IDs are used as keys to the map. The values are moved from the old key + * (the old ID) to the new key (the new ID) within the same map. {@code null} is + * used as the default or "empty" value. + */ +public class Id2ObjectBiMapMapper implements IdMapper { + + public static Id2ObjectBiMapMapper of(Id2ObjectBiMap registry) { + return new Id2ObjectBiMapMapper(registry); + } + + private final Id2ObjectBiMap registry; + private final Id2ObjectBiMap backup; + + private boolean applied; + + @SuppressWarnings("unchecked") + private Id2ObjectBiMapMapper(Id2ObjectBiMap registry) { + this.registry = (Id2ObjectBiMap) registry; + this.backup = new Id2ObjectBiMap<>(registry.size()); + } + + /* + * unlike Registry, Id2ObjectBiMap allows duplicate values + * thus iterating over all values will not give you all id-value pairs! + */ + + @Override + public void apply(RegistryMappings mappings) { + this.backup.osl$registries$clear(); + + for (int id : this.registry.osl$registries$idSet()) { + this.backup.put(this.registry.get(id), id); + } + + this.registry.osl$registries$clear(); + + for (int oldId : this.backup.osl$registries$idSet()) { + Object value = this.backup.get(oldId); + int newId = mappings.remap(oldId); + + if (newId >= 0) { + this.registry.put(value, newId); + } + } + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + this.registry.osl$registries$clear(); + + for (int id : this.backup.osl$registries$idSet()) { + this.registry.put(this.backup.get(id), id); + } + } + + this.applied = false; + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java new file mode 100644 index 000000000..f6896b0bd --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,43 @@ +package net.ornithemc.osl.registries.impl; + +import net.minecraft.text.LiteralText; + +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.api.client.ClientPlayNetworking; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +public final class RegistriesEntrypoint implements ClientModInitializer { + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(Constants.OSL_REGISTRY_SYNC_CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesPacketSerializer.deserialize(buffer, RegistryMappingSource.REMOTE_SERVER); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.applyMappings(); + }); + } catch (RegistryMappingException e) { + RegistriesImpl.LOGGER.error("Unable to remap registries!", e); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.resetMappings(); + + if (context.networkHandler().getConnection().isConnected()) { + context.networkHandler().getConnection().disconnect(new LiteralText("Failed to remap registries: " + e.getMessage())); + } + }); + } + }); + ClientConnectionEvents.DISCONNECT.register(context -> { + if (!context.isServerLocal()) { + SyncedRegistriesImpl.undoMappings(); + } + }); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java new file mode 100644 index 000000000..d7017be43 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java @@ -0,0 +1,16 @@ +package net.ornithemc.osl.registries.impl.access; + +public interface Clearable { + + static void clear(Object o) { + if (o instanceof Clearable) { + ((Clearable) o).osl$registries$clear(); + } else { + throw new IllegalArgumentException("not clearable: " + o); + } + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess.java new file mode 100644 index 000000000..d0437d3ac --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.access; + +import it.unimi.dsi.fastutil.ints.IntSet; + +public interface Id2ObjectBiMapAccess { + + default IntSet osl$registries$idSet() { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java new file mode 100644 index 000000000..83f069aa5 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java @@ -0,0 +1,20 @@ +package net.ornithemc.osl.registries.impl.access; + +import net.minecraft.resource.Identifier; + +public interface IdRegistryAccess { + + default void osl$registries$setCallback(RegisterCallback callback) { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } + + interface RegisterCallback { + + void valueRegistered(int id, Identifier key, Object value); + + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java new file mode 100644 index 000000000..ea596a58c --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java @@ -0,0 +1,11 @@ +package net.ornithemc.osl.registries.impl.access; + +import java.io.IOException; + +public interface WorldStorageAccess { + + void osl$registries$loadRegistryMappings() throws IOException; + + void osl$registries$saveRegistryMappings() throws IOException; + +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java new file mode 100644 index 000000000..16d16aa6b --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java @@ -0,0 +1,49 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import java.io.IOException; + +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.sugar.Local; + +import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.util.crash.CrashException; +import net.minecraft.util.crash.CrashReport; +import net.minecraft.world.storage.WorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(IntegratedServer.class) +public class IntegratedServerMixin { + + @Inject( + method = "loadWorld", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/storage/WorldStorage;loadData()Lnet/minecraft/world/WorldData;" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci, @Local WorldStorage storage) { + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$loadRegistryMappings(); + } catch (IOException e) { + throw new CrashException(CrashReport.of(e, "Exception initializing level")); + } + } + } + + @Inject( + method = "shutdown", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$unmapRegistries(CallbackInfo ci) { + SyncedRegistriesImpl.undoMappings(); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java new file mode 100644 index 000000000..f7de606ca --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,116 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.storage.AlphaWorldStorage; + +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesNbtSerializer; + +@Mixin(AlphaWorldStorage.class) +public class AlphaWorldStorageMixin implements WorldStorageAccess { + + @Shadow @Final + private String name; + + @Shadow + private File getDirectory() { return null; } + + @Override + public void osl$registries$loadRegistryMappings() throws IOException { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + + if (!this.readRegistryMappings(file, false)) { + file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + if (!this.readRegistryMappings(file, true)) { + RegistriesImpl.LOGGER.debug("no registry mappings read for '" + this.name + "'"); + } + } + } + + @Unique + private boolean readRegistryMappings(File file, boolean throwOnException) throws IOException { + if (file.exists()) { + try (InputStream is = new FileInputStream(file)) { + NbtCompound nbt = NbtIo.readCompressed(is); + + SyncedRegistriesNbtSerializer.deserialize(nbt, RegistryMappingSource.WORLD_SAVE); + SyncedRegistriesImpl.applyMappings(); + + return true; + } catch (IOException e) { + if (throwOnException) { + throw new IOException("Unable to read registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("error while reading registry mappings for '" + this.name + "'", e); + } + } catch (RegistryMappingException e) { + if (throwOnException) { + throw new IOException("Invalid registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("invalid registry mappings for '" + this.name + "'", e); + } + } + } + + return false; + } + + @Override + public void osl$registries$saveRegistryMappings() throws IOException { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + File tmp = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_tmp"); + File backup = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + this.writeRegistryMappings(file, tmp, backup); + } + + @Unique + private void writeRegistryMappings(File file, File newFile, File oldFile) throws IOException { + NbtCompound nbt = new NbtCompound(); + + try { + SyncedRegistriesNbtSerializer.serialize(nbt); + + try (OutputStream os = new FileOutputStream(newFile)) { + NbtIo.writeCompressed(nbt, os); + } + + if (oldFile.exists()) { + oldFile.delete(); + } + + file.renameTo(oldFile); + if (file.exists()) { + file.delete(); + } + + newFile.renameTo(file); + if (newFile.exists()) { + newFile.delete(); + } + } catch (IOException e) { + RegistriesImpl.LOGGER.warn("error while writing registry mappings for '" + this.name + "'", e); + } + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java new file mode 100644 index 000000000..773df9d09 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Arrays; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; + +import net.ornithemc.osl.registries.impl.access.Clearable; + +@Mixin(CrudeIncrementalIntIdentityHashMap.class) +public class CrudeIncrementalIntIdentityHashMapMixin implements Clearable { + + @Shadow + private Object[] keys; + @Shadow + private Object[] byId; + + @Shadow + private int nextId; + @Shadow + private int size; + + @Override + public void osl$registries$clear() { + Arrays.fill(this.keys, null); + Arrays.fill(this.byId, null); + + this.nextId = 0; + this.size = 0; + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java new file mode 100644 index 000000000..79f753e2f --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java @@ -0,0 +1,15 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.DefaultedIdRegistry; + +@Mixin(DefaultedIdRegistry.class) +public interface DefaultedIdRegistryAccess { + + @Accessor("defaultId") + Identifier accessDefaultId(); + +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java new file mode 100644 index 000000000..3a3ce1078 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java @@ -0,0 +1,59 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.IdentityHashMap; +import java.util.List; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; + +import net.minecraft.util.Id2ObjectBiMap; + +import net.ornithemc.osl.registries.impl.access.Clearable; +import net.ornithemc.osl.registries.impl.access.Id2ObjectBiMapAccess; + +@Mixin(Id2ObjectBiMap.class) +public class Id2ObjectBiMapMixin implements Id2ObjectBiMapAccess, Clearable { + + @Shadow @Final + private List values; + @Shadow @Final + private IdentityHashMap ids; + + @Shadow + private int nextId; + + @Unique + private final IntSet idSet = new IntOpenHashSet(); + + @Inject( + method = "put(Ljava/lang/Object;I)V", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$put(T value, int id, CallbackInfo ci) { + this.idSet.add(id); + } + + @Override + public IntSet osl$registries$idSet() { + return this.idSet; + } + + @Override + public void osl$registries$clear() { + this.values.clear(); + this.ids.clear(); + this.idSet.clear(); + + this.nextId = 0; + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java new file mode 100644 index 000000000..7378175ca --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java @@ -0,0 +1,53 @@ +package net.ornithemc.osl.registries.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.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.google.common.collect.BiMap; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.registries.impl.access.Clearable; +import net.ornithemc.osl.registries.impl.access.IdRegistryAccess; + +@Mixin(IdRegistry.class) +public class IdRegistryMixin implements IdRegistryAccess, Clearable { + + @Shadow @Final + private CrudeIncrementalIntIdentityHashMap ids; + @Shadow @Final + private BiMap values; + + @Unique + private RegisterCallback callback; + + @Inject( + method = "register", + at = @At( + value = "RETURN" + ) + ) + private void osl$registries$register(int id, Identifier key, T value, CallbackInfo ci) { + if (this.callback != null) { + this.callback.valueRegistered(id, key, value); + } + } + + @Override + public void osl$registries$setCallback(RegisterCallback callback) { + this.callback = callback; + } + + @Override + public void osl$registries$clear() { + this.values.clear(); + Clearable.clear(this.ids); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java new file mode 100644 index 000000000..fd559a78c --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java @@ -0,0 +1,62 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.IOException; + +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.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.crash.CrashException; +import net.minecraft.util.crash.CrashReport; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.storage.WorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + + @Inject( + method = "loadWorld", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/storage/WorldStorage;loadData()Lnet/minecraft/world/WorldData;" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci, @Local WorldStorage storage) { + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$loadRegistryMappings(); + } catch (IOException e) { + throw new CrashException(CrashReport.of(e, "Exception initializing level")); + } + } + } + + @Inject( + method = "saveWorlds", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(CallbackInfo ci) { + MinecraftServer server = (MinecraftServer) (Object) this; + + ServerWorld overworld = server.getWorld(DimensionType.OVERWORLD); + WorldStorage storage = overworld.getStorage(); + + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$saveRegistryMappings(); + } catch (IOException e) { + RegistriesImpl.LOGGER.error("Exception saving level", e); + } + } + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java new file mode 100644 index 000000000..01174aa6b --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.registries.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 com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerPlayNetworking; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final + private MinecraftServer server; + + @Inject( + method = "onLogin", + at = @At( + value = "NEW", + target = "net/minecraft/network/packet/s2c/play/LoginS2CPacket" + ) + ) + private void osl$idsync$syncRegistries(CallbackInfo ci, @Local ServerPlayerEntity player) { + if (this.server.isDedicated() || !this.server.getUsername().equals(player.getGameProfile().getName())) { + ServerPlayNetworking.sendNoCheck(player, Constants.OSL_REGISTRY_SYNC_CHANNEL, SyncedRegistriesPacketSerializer::serialize); + } + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/RegistryMixin.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/RegistryMixin.java new file mode 100644 index 000000000..3ec07e28b --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/RegistryMixin.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.registries.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.util.registry.Registry; + +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(Registry.class) +public interface RegistryMixin { + + @Inject( + method = "init", + at = @At( + value = "HEAD" + ) + ) + static void osl$registries$initRegistries(CallbackInfo ci) { + RegistriesImpl.init(); + SyncedRegistriesImpl.init(); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java new file mode 100644 index 000000000..9cdf561fc --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java @@ -0,0 +1,19 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.util.registry.DefaultedIdRegistry; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public final class VanillaRegistries { + + public static Registry registerSimple(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return RegistriesImpl.register(key, WrappedIdRegistry.of(key, (IdRegistry) registry), () -> { }); + } + + public static DefaultedRegistry registerDefaulted(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return RegistriesImpl.register(key, WrappedDefaultedIdRegistry.of(key, (DefaultedIdRegistry) registry), () -> { }); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java new file mode 100644 index 000000000..d1cf93ce7 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java @@ -0,0 +1,25 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.util.registry.DefaultedIdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.impl.mixin.common.DefaultedIdRegistryAccess; + +public class WrappedDefaultedIdRegistry extends WrappedIdRegistry implements DefaultedRegistry { + + public static WrappedDefaultedIdRegistry of(ResourceKey> key, DefaultedIdRegistry registry) { + return new WrappedDefaultedIdRegistry<>(key.identifier(), registry); + } + + private WrappedDefaultedIdRegistry(NamespacedIdentifier identifier, DefaultedIdRegistry registry) { + super(identifier, registry); + } + + @Override + public NamespacedIdentifier getDefaultIdentifier() { + return this.serializeKey(((DefaultedIdRegistryAccess) this.registry).accessDefaultId()); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java new file mode 100644 index 000000000..d7ef65e06 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java @@ -0,0 +1,131 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.Iterator; +import java.util.Set; +import java.util.stream.Collectors; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.ResourceKeys; + +public class WrappedIdRegistry implements ClearableRegistry { + + public static WrappedIdRegistry of(ResourceKey> key, IdRegistry registry) { + return new WrappedIdRegistry<>(key.identifier(), registry); + } + + final NamespacedIdentifier identifier; + final IdRegistry registry; + + private int nextId; + private boolean frozen; + + WrappedIdRegistry(NamespacedIdentifier identifier, IdRegistry registry) { + this.identifier = identifier; + this.registry = registry; + + this.registry.osl$registries$setCallback(this::valueRegistered); + } + + NamespacedIdentifier serializeKey(Identifier key) { + return key; + } + + Identifier deserializeKey(NamespacedIdentifier identifier) { + return identifier == null ? null : (identifier instanceof Identifier ? (Identifier) identifier : new Identifier(identifier.namespace(), identifier.identifier())); + } + + ResourceKey resourceKey(NamespacedIdentifier identifier) { + return identifier == null ? null : ResourceKeys.from(this.identifier, identifier); + } + + private void valueRegistered(int id, Identifier key, Object value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + + this.nextId = Math.max(this.nextId, id + 1); + } + + @Override + public V register(ResourceKey key, V value) { + return this.register(this.nextId, key, value); + } + + @Override + public V register(int id, ResourceKey key, V value) { + this.registry.register(id, this.deserializeKey(key.identifier()), value); + return value; + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } + + @Override + public T get(int id) { + return this.registry.get(id); + } + + @Override + public T get(ResourceKey key) { + return this.registry.get(this.deserializeKey(key.identifier())); + } + + @Override + public T get(NamespacedIdentifier identifier) { + return this.registry.get(this.deserializeKey(identifier)); + } + + @Override + public int getId(T value) { + return this.registry.getId(value); + } + + @Override + public ResourceKey getKey(T value) { + return this.resourceKey(this.serializeKey(this.registry.getKey(value))); + } + + @Override + public NamespacedIdentifier getIdentifier(T value) { + return this.serializeKey(this.registry.getKey(value)); + } + + @Override + public Set> keySet() { + return this.registry.keySet().stream().map(this::serializeKey).map(this::resourceKey).collect(Collectors.toSet()); + } + + @Override + public Set identifierSet() { + return this.registry.keySet().stream().map(this::serializeKey).collect(Collectors.toSet()); + } + + @Override + public Iterator iterator() { + return this.registry.iterator(); + } + + @Override + public Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public void clear() { + this.registry.osl$registries$clear(); + + this.nextId = 0; + this.frozen = false; + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java new file mode 100644 index 000000000..b2b48ca34 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java @@ -0,0 +1,78 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.minecraft.nbt.NbtCompound; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesNbtSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(NbtCompound nbt) throws IOException { + NbtCompound registriesNbt = new NbtCompound(); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt, SyncedRegistriesNbtSerializer::serialize); + registriesNbt.put(identifier.toString(), mappingsNbt); + } + + nbt.putInt(Constants.FORMAT_NBT_KEY, Constants.REGISTRY_MAPPINGS_FORMAT); + nbt.put(Constants.REGISTRIES_NBT_KEY, registriesNbt); + } + + public static void deserialize(NbtCompound nbt, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = nbt.getInt(Constants.FORMAT_NBT_KEY); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + NbtCompound registriesNbt = nbt.getCompound(Constants.REGISTRIES_NBT_KEY); + + for (String key : registriesNbt.getKeys()) { + NbtCompound mappingsNbt = registriesNbt.getCompound(key); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(key); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(mappingsNbt, SyncedRegistriesNbtSerializer::deserialize, source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(NbtCompound nbt, Object2IntMap mappings) throws IOException { + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } + + public static void deserialize(NbtCompound nbt, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + for (String key : nbt.getKeys()) { + mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java new file mode 100644 index 000000000..d21165816 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java @@ -0,0 +1,81 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesPacketSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(Constants.REGISTRY_MAPPINGS_FORMAT); + buffer.writeVarInt(REGISTRIES.keySet().size()); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer, SyncedRegistriesPacketSerializer::serialize); + } + } + + public static void deserialize(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(buffer, SyncedRegistriesPacketSerializer::deserialize, source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(PacketBuffer buffer, Object2IntMap mappings) throws IOException { + buffer.writeVarInt(mappings.size()); + + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public static void deserialize(PacketBuffer buffer, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + mappings.put(identifier, id); + } + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..772a1eca8 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json @@ -0,0 +1,37 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc18w32a-mc1.13.2", + "environment": "*", + "entrypoints": { + "client-init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ] + }, + "mixins": [ + "osl.registries.mixins.json" + ], + "accessWidener": "osl.registries.classtweaker", + "depends": { + "fabricloader": "\u003e\u003d0.18.0", + "minecraft": "\u003e\u003d1.13.1-alpha.18.32.a \u003c\u003d1.13.2", + "osl-core": "\u003e\u003d0.8.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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0" + }, + "name": "OSL Registries", + "description": "Registries API and numerical ID synchronization.", + "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/registries/registries-mc18w32a-mc1.13.2/src/main/resources/osl.registries.classtweaker b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/osl.registries.classtweaker new file mode 100644 index 000000000..9cbd4bc0c --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/osl.registries.classtweaker @@ -0,0 +1,4 @@ +classTweaker v1 named + +inject-interface net/minecraft/util/Id2ObjectBiMap net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess +inject-interface net/minecraft/util/registry/IdRegistry net/ornithemc/osl/registries/impl/access/IdRegistryAccess diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/osl.registries.mixins.json b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/osl.registries.mixins.json new file mode 100644 index 000000000..2b3ab4934 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,24 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.CrudeIncrementalIntIdentityHashMapMixin", + "common.DefaultedIdRegistryAccess", + "common.Id2ObjectBiMapMixin", + "common.IdRegistryMixin", + "common.MinecraftServerMixin", + "common.PlayerManagerMixin", + "common.RegistryMixin" + ], + "client": [ + "client.IntegratedServerMixin" + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/build.gradle b/libraries/registries/registries-mc18w43a-mc19w03c/build.gradle new file mode 100644 index 000000000..0a350fdb3 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/build.gradle @@ -0,0 +1 @@ +setUpModule(project) diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/gradle.properties b/libraries/registries/registries-mc18w43a-mc19w03c/gradle.properties new file mode 100644 index 000000000..4bccc1c48 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/gradle.properties @@ -0,0 +1,5 @@ +min_mc_version = 18w43a +max_mc_version = 19w03c +minecraft_dependency = >=1.14-alpha.18.43.a <=1.14-alpha.19.3.c + +minecraft_version = 19w03c 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 new file mode 100644 index 000000000..87d5b78ad --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; + +/** + * Utility class containing commonly used registry keys (i.e. @linkplain + * ResourceKey resource keys} for registries), as well as factory methods + * for creating registry keys. + */ +public final class RegistryKeys { + + public static final ResourceKey> BLOCK = from("block"); + public static final ResourceKey> ITEM = from("item"); + + /** + * Constructs a registry key with the default namespace and the given identifier. + * + * @param the value type of the registry. + * @param identifier the identifier of the registry. + * @return the constructed registry key. + */ + public static ResourceKey> from(String identifier) { + return from(NamespacedIdentifiers.from(identifier)); + } + + /** + * Constructs a registry key with the given namespaced identifier. + * + * @param the value type of the registry. + * @param identifier the namespaced identifier of the registry. + * @return the constructed registry key. + */ + public static ResourceKey> from(NamespacedIdentifier identifier) { + return ResourceKeys.from(identifier); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java new file mode 100644 index 000000000..544daace9 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java @@ -0,0 +1,67 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import net.minecraft.util.Id2ObjectBiMap; + +/** + * An {@linkplain IdMapper} implementation for {@linkplain Id2ObjectBiMap}s + * where IDs are used as keys to the map. The values are moved from the old key + * (the old ID) to the new key (the new ID) within the same map. {@code null} is + * used as the default or "empty" value. + */ +public class Id2ObjectBiMapMapper implements IdMapper { + + public static Id2ObjectBiMapMapper of(Id2ObjectBiMap registry) { + return new Id2ObjectBiMapMapper(registry); + } + + private final Id2ObjectBiMap registry; + private final Id2ObjectBiMap backup; + + private boolean applied; + + @SuppressWarnings("unchecked") + private Id2ObjectBiMapMapper(Id2ObjectBiMap registry) { + this.registry = (Id2ObjectBiMap) registry; + this.backup = new Id2ObjectBiMap<>(registry.size()); + } + + /* + * unlike Registry, Id2ObjectBiMap allows duplicate values + * thus iterating over all values will not give you all id-value pairs! + */ + + @Override + public void apply(RegistryMappings mappings) { + this.backup.osl$registries$clear(); + + for (int id : this.registry.osl$registries$idSet()) { + this.backup.put(this.registry.get(id), id); + } + + this.registry.osl$registries$clear(); + + for (int oldId : this.backup.osl$registries$idSet()) { + Object value = this.backup.get(oldId); + int newId = mappings.remap(oldId); + + if (newId >= 0) { + this.registry.put(value, newId); + } + } + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + this.registry.osl$registries$clear(); + + for (int id : this.backup.osl$registries$idSet()) { + this.registry.put(this.backup.get(id), id); + } + } + + this.applied = false; + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java new file mode 100644 index 000000000..f6896b0bd --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,43 @@ +package net.ornithemc.osl.registries.impl; + +import net.minecraft.text.LiteralText; + +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.api.client.ClientPlayNetworking; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +public final class RegistriesEntrypoint implements ClientModInitializer { + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(Constants.OSL_REGISTRY_SYNC_CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesPacketSerializer.deserialize(buffer, RegistryMappingSource.REMOTE_SERVER); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.applyMappings(); + }); + } catch (RegistryMappingException e) { + RegistriesImpl.LOGGER.error("Unable to remap registries!", e); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.resetMappings(); + + if (context.networkHandler().getConnection().isConnected()) { + context.networkHandler().getConnection().disconnect(new LiteralText("Failed to remap registries: " + e.getMessage())); + } + }); + } + }); + ClientConnectionEvents.DISCONNECT.register(context -> { + if (!context.isServerLocal()) { + SyncedRegistriesImpl.undoMappings(); + } + }); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java new file mode 100644 index 000000000..d7017be43 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java @@ -0,0 +1,16 @@ +package net.ornithemc.osl.registries.impl.access; + +public interface Clearable { + + static void clear(Object o) { + if (o instanceof Clearable) { + ((Clearable) o).osl$registries$clear(); + } else { + throw new IllegalArgumentException("not clearable: " + o); + } + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess.java new file mode 100644 index 000000000..d0437d3ac --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.access; + +import it.unimi.dsi.fastutil.ints.IntSet; + +public interface Id2ObjectBiMapAccess { + + default IntSet osl$registries$idSet() { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java new file mode 100644 index 000000000..83f069aa5 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java @@ -0,0 +1,20 @@ +package net.ornithemc.osl.registries.impl.access; + +import net.minecraft.resource.Identifier; + +public interface IdRegistryAccess { + + default void osl$registries$setCallback(RegisterCallback callback) { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } + + interface RegisterCallback { + + void valueRegistered(int id, Identifier key, Object value); + + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java new file mode 100644 index 000000000..ea596a58c --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java @@ -0,0 +1,11 @@ +package net.ornithemc.osl.registries.impl.access; + +import java.io.IOException; + +public interface WorldStorageAccess { + + void osl$registries$loadRegistryMappings() throws IOException; + + void osl$registries$saveRegistryMappings() throws IOException; + +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java new file mode 100644 index 000000000..16d16aa6b --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java @@ -0,0 +1,49 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import java.io.IOException; + +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.sugar.Local; + +import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.util.crash.CrashException; +import net.minecraft.util.crash.CrashReport; +import net.minecraft.world.storage.WorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(IntegratedServer.class) +public class IntegratedServerMixin { + + @Inject( + method = "loadWorld", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/storage/WorldStorage;loadData()Lnet/minecraft/world/WorldData;" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci, @Local WorldStorage storage) { + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$loadRegistryMappings(); + } catch (IOException e) { + throw new CrashException(CrashReport.of(e, "Exception initializing level")); + } + } + } + + @Inject( + method = "shutdown", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$unmapRegistries(CallbackInfo ci) { + SyncedRegistriesImpl.undoMappings(); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java new file mode 100644 index 000000000..f7de606ca --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,116 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.storage.AlphaWorldStorage; + +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesNbtSerializer; + +@Mixin(AlphaWorldStorage.class) +public class AlphaWorldStorageMixin implements WorldStorageAccess { + + @Shadow @Final + private String name; + + @Shadow + private File getDirectory() { return null; } + + @Override + public void osl$registries$loadRegistryMappings() throws IOException { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + + if (!this.readRegistryMappings(file, false)) { + file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + if (!this.readRegistryMappings(file, true)) { + RegistriesImpl.LOGGER.debug("no registry mappings read for '" + this.name + "'"); + } + } + } + + @Unique + private boolean readRegistryMappings(File file, boolean throwOnException) throws IOException { + if (file.exists()) { + try (InputStream is = new FileInputStream(file)) { + NbtCompound nbt = NbtIo.readCompressed(is); + + SyncedRegistriesNbtSerializer.deserialize(nbt, RegistryMappingSource.WORLD_SAVE); + SyncedRegistriesImpl.applyMappings(); + + return true; + } catch (IOException e) { + if (throwOnException) { + throw new IOException("Unable to read registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("error while reading registry mappings for '" + this.name + "'", e); + } + } catch (RegistryMappingException e) { + if (throwOnException) { + throw new IOException("Invalid registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("invalid registry mappings for '" + this.name + "'", e); + } + } + } + + return false; + } + + @Override + public void osl$registries$saveRegistryMappings() throws IOException { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + File tmp = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_tmp"); + File backup = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + this.writeRegistryMappings(file, tmp, backup); + } + + @Unique + private void writeRegistryMappings(File file, File newFile, File oldFile) throws IOException { + NbtCompound nbt = new NbtCompound(); + + try { + SyncedRegistriesNbtSerializer.serialize(nbt); + + try (OutputStream os = new FileOutputStream(newFile)) { + NbtIo.writeCompressed(nbt, os); + } + + if (oldFile.exists()) { + oldFile.delete(); + } + + file.renameTo(oldFile); + if (file.exists()) { + file.delete(); + } + + newFile.renameTo(file); + if (newFile.exists()) { + newFile.delete(); + } + } catch (IOException e) { + RegistriesImpl.LOGGER.warn("error while writing registry mappings for '" + this.name + "'", e); + } + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java new file mode 100644 index 000000000..7b6b88a17 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.registries.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 net.minecraft.Bootstrap; +import net.minecraft.util.registry.Registry; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(Bootstrap.class) +public class BootstrapMixin { + + @Inject( + method = "init", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/util/registry/Registry;REGISTRY:Lnet/minecraft/unmapped/C_06803903;", + opcode = Opcodes.GETSTATIC + ) + ) + private static void osl$registries$initRegistries(CallbackInfo ci) { + // force registry loading (the targeted field access does the same) + Registry.REGISTRY.getClass(); + + RegistriesImpl.init(); + SyncedRegistriesImpl.init(); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java new file mode 100644 index 000000000..773df9d09 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Arrays; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; + +import net.ornithemc.osl.registries.impl.access.Clearable; + +@Mixin(CrudeIncrementalIntIdentityHashMap.class) +public class CrudeIncrementalIntIdentityHashMapMixin implements Clearable { + + @Shadow + private Object[] keys; + @Shadow + private Object[] byId; + + @Shadow + private int nextId; + @Shadow + private int size; + + @Override + public void osl$registries$clear() { + Arrays.fill(this.keys, null); + Arrays.fill(this.byId, null); + + this.nextId = 0; + this.size = 0; + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java new file mode 100644 index 000000000..79f753e2f --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java @@ -0,0 +1,15 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.DefaultedIdRegistry; + +@Mixin(DefaultedIdRegistry.class) +public interface DefaultedIdRegistryAccess { + + @Accessor("defaultId") + Identifier accessDefaultId(); + +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java new file mode 100644 index 000000000..3a3ce1078 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java @@ -0,0 +1,59 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.IdentityHashMap; +import java.util.List; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; + +import net.minecraft.util.Id2ObjectBiMap; + +import net.ornithemc.osl.registries.impl.access.Clearable; +import net.ornithemc.osl.registries.impl.access.Id2ObjectBiMapAccess; + +@Mixin(Id2ObjectBiMap.class) +public class Id2ObjectBiMapMixin implements Id2ObjectBiMapAccess, Clearable { + + @Shadow @Final + private List values; + @Shadow @Final + private IdentityHashMap ids; + + @Shadow + private int nextId; + + @Unique + private final IntSet idSet = new IntOpenHashSet(); + + @Inject( + method = "put(Ljava/lang/Object;I)V", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$put(T value, int id, CallbackInfo ci) { + this.idSet.add(id); + } + + @Override + public IntSet osl$registries$idSet() { + return this.idSet; + } + + @Override + public void osl$registries$clear() { + this.values.clear(); + this.ids.clear(); + this.idSet.clear(); + + this.nextId = 0; + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java new file mode 100644 index 000000000..02a70e1be --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java @@ -0,0 +1,53 @@ +package net.ornithemc.osl.registries.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.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import com.google.common.collect.BiMap; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.registries.impl.access.Clearable; +import net.ornithemc.osl.registries.impl.access.IdRegistryAccess; + +@Mixin(IdRegistry.class) +public class IdRegistryMixin implements IdRegistryAccess, Clearable { + + @Shadow @Final + private CrudeIncrementalIntIdentityHashMap ids; + @Shadow @Final + private BiMap values; + + @Unique + private RegisterCallback callback; + + @Inject( + method = "m_26252208", + at = @At( + value = "RETURN" + ) + ) + private void osl$registries$register(int id, Identifier key, T value, CallbackInfoReturnable cir) { + if (this.callback != null) { + this.callback.valueRegistered(id, key, value); + } + } + + @Override + public void osl$registries$setCallback(RegisterCallback callback) { + this.callback = callback; + } + + @Override + public void osl$registries$clear() { + this.values.clear(); + Clearable.clear(this.ids); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java new file mode 100644 index 000000000..3c06c9618 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java @@ -0,0 +1,63 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.IOException; + +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.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.crash.CrashException; +import net.minecraft.util.crash.CrashReport; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.storage.WorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + + @Inject( + method = "loadWorld", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/storage/WorldStorage;loadData()Lnet/minecraft/world/WorldData;" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci, @Local WorldStorage storage) { + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$loadRegistryMappings(); + } catch (IOException e) { + throw new CrashException(CrashReport.of(e, "Exception initializing level")); + } + } + } + + @Inject( + method = "saveWorlds", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(CallbackInfo ci) { + @SuppressWarnings("resource") + MinecraftServer server = (MinecraftServer) (Object) this; + + ServerWorld overworld = server.getWorld(DimensionType.OVERWORLD); + WorldStorage storage = overworld.getStorage(); + + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$saveRegistryMappings(); + } catch (IOException e) { + RegistriesImpl.LOGGER.error("Exception saving level", e); + } + } + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java new file mode 100644 index 000000000..01174aa6b --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.registries.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 com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerPlayNetworking; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final + private MinecraftServer server; + + @Inject( + method = "onLogin", + at = @At( + value = "NEW", + target = "net/minecraft/network/packet/s2c/play/LoginS2CPacket" + ) + ) + private void osl$idsync$syncRegistries(CallbackInfo ci, @Local ServerPlayerEntity player) { + if (this.server.isDedicated() || !this.server.getUsername().equals(player.getGameProfile().getName())) { + ServerPlayNetworking.sendNoCheck(player, Constants.OSL_REGISTRY_SYNC_CHANNEL, SyncedRegistriesPacketSerializer::serialize); + } + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java new file mode 100644 index 000000000..9cdf561fc --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java @@ -0,0 +1,19 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.util.registry.DefaultedIdRegistry; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public final class VanillaRegistries { + + public static Registry registerSimple(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return RegistriesImpl.register(key, WrappedIdRegistry.of(key, (IdRegistry) registry), () -> { }); + } + + public static DefaultedRegistry registerDefaulted(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return RegistriesImpl.register(key, WrappedDefaultedIdRegistry.of(key, (DefaultedIdRegistry) registry), () -> { }); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java new file mode 100644 index 000000000..d1cf93ce7 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java @@ -0,0 +1,25 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.util.registry.DefaultedIdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.impl.mixin.common.DefaultedIdRegistryAccess; + +public class WrappedDefaultedIdRegistry extends WrappedIdRegistry implements DefaultedRegistry { + + public static WrappedDefaultedIdRegistry of(ResourceKey> key, DefaultedIdRegistry registry) { + return new WrappedDefaultedIdRegistry<>(key.identifier(), registry); + } + + private WrappedDefaultedIdRegistry(NamespacedIdentifier identifier, DefaultedIdRegistry registry) { + super(identifier, registry); + } + + @Override + public NamespacedIdentifier getDefaultIdentifier() { + return this.serializeKey(((DefaultedIdRegistryAccess) this.registry).accessDefaultId()); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java new file mode 100644 index 000000000..6d0df9147 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java @@ -0,0 +1,133 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.Iterator; +import java.util.Set; +import java.util.stream.Collectors; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.ResourceKeys; + +public class WrappedIdRegistry implements ClearableRegistry { + + public static WrappedIdRegistry of(ResourceKey> key, IdRegistry registry) { + return new WrappedIdRegistry<>(key.identifier(), registry); + } + + final NamespacedIdentifier identifier; + final IdRegistry registry; + + private int nextId; + private boolean frozen; + + WrappedIdRegistry(NamespacedIdentifier identifier, IdRegistry registry) { + this.identifier = identifier; + this.registry = registry; + + this.registry.osl$registries$setCallback(this::valueRegistered); + } + + NamespacedIdentifier serializeKey(Identifier key) { + return key; + } + + Identifier deserializeKey(NamespacedIdentifier identifier) { + return identifier == null ? null : (identifier instanceof Identifier ? (Identifier) identifier : new Identifier(identifier.namespace(), identifier.identifier())); + } + + ResourceKey resourceKey(NamespacedIdentifier identifier) { + return identifier == null ? null : ResourceKeys.from(this.identifier, identifier); + } + + private void valueRegistered(int id, Identifier key, Object value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + + this.nextId = Math.max(this.nextId, id + 1); + } + + @Override + public V register(ResourceKey key, V value) { + return this.register(this.nextId, key, value); + } + + @Override + public V register(int id, ResourceKey key, V value) { + this.registry.m_26252208(id, this.deserializeKey(key.identifier()), value); + return value; + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } + + @Override + public T get(int id) { + return this.registry.get(id); + } + + @Override + public T get(ResourceKey key) { + Identifier k = this.deserializeKey(key.identifier()); + return this.registry.containsKey(k) ? this.registry.getOrDefault(k) : null; + } + + @Override + public T get(NamespacedIdentifier identifier) { + Identifier k = this.deserializeKey(identifier); + return this.registry.containsKey(k) ? this.registry.getOrDefault(k) : null; + } + + @Override + public int getId(T value) { + return this.registry.getId(value); + } + + @Override + public ResourceKey getKey(T value) { + return this.resourceKey(this.serializeKey(this.registry.getKey(value))); + } + + @Override + public NamespacedIdentifier getIdentifier(T value) { + return this.serializeKey(this.registry.getKey(value)); + } + + @Override + public Set> keySet() { + return this.registry.keySet().stream().map(this::serializeKey).map(this::resourceKey).collect(Collectors.toSet()); + } + + @Override + public Set identifierSet() { + return this.registry.keySet().stream().map(this::serializeKey).collect(Collectors.toSet()); + } + + @Override + public Iterator iterator() { + return this.registry.iterator(); + } + + @Override + public Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public void clear() { + this.registry.osl$registries$clear(); + + this.nextId = 0; + this.frozen = false; + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java new file mode 100644 index 000000000..b2b48ca34 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java @@ -0,0 +1,78 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.minecraft.nbt.NbtCompound; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesNbtSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(NbtCompound nbt) throws IOException { + NbtCompound registriesNbt = new NbtCompound(); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt, SyncedRegistriesNbtSerializer::serialize); + registriesNbt.put(identifier.toString(), mappingsNbt); + } + + nbt.putInt(Constants.FORMAT_NBT_KEY, Constants.REGISTRY_MAPPINGS_FORMAT); + nbt.put(Constants.REGISTRIES_NBT_KEY, registriesNbt); + } + + public static void deserialize(NbtCompound nbt, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = nbt.getInt(Constants.FORMAT_NBT_KEY); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + NbtCompound registriesNbt = nbt.getCompound(Constants.REGISTRIES_NBT_KEY); + + for (String key : registriesNbt.getKeys()) { + NbtCompound mappingsNbt = registriesNbt.getCompound(key); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(key); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(mappingsNbt, SyncedRegistriesNbtSerializer::deserialize, source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(NbtCompound nbt, Object2IntMap mappings) throws IOException { + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } + + public static void deserialize(NbtCompound nbt, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + for (String key : nbt.getKeys()) { + mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java new file mode 100644 index 000000000..d21165816 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java @@ -0,0 +1,81 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesPacketSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(Constants.REGISTRY_MAPPINGS_FORMAT); + buffer.writeVarInt(REGISTRIES.keySet().size()); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer, SyncedRegistriesPacketSerializer::serialize); + } + } + + public static void deserialize(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(buffer, SyncedRegistriesPacketSerializer::deserialize, source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(PacketBuffer buffer, Object2IntMap mappings) throws IOException { + buffer.writeVarInt(mappings.size()); + + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public static void deserialize(PacketBuffer buffer, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + mappings.put(identifier, id); + } + } +} diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/resources/fabric.mod.json b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..3f42e7b71 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/resources/fabric.mod.json @@ -0,0 +1,37 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc18w43a-mc19w03c", + "environment": "*", + "entrypoints": { + "client-init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ] + }, + "mixins": [ + "osl.registries.mixins.json" + ], + "accessWidener": "osl.registries.classtweaker", + "depends": { + "fabricloader": "\u003e\u003d0.18.0", + "minecraft": "\u003e\u003d1.14-alpha.18.43.a \u003c\u003d1.14-alpha.19.3.c", + "osl-core": "\u003e\u003d0.8.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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0" + }, + "name": "OSL Registries", + "description": "Registries API and numerical ID synchronization.", + "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/registries/registries-mc18w43a-mc19w03c/src/main/resources/osl.registries.classtweaker b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/resources/osl.registries.classtweaker new file mode 100644 index 000000000..9cbd4bc0c --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/resources/osl.registries.classtweaker @@ -0,0 +1,4 @@ +classTweaker v1 named + +inject-interface net/minecraft/util/Id2ObjectBiMap net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess +inject-interface net/minecraft/util/registry/IdRegistry net/ornithemc/osl/registries/impl/access/IdRegistryAccess diff --git a/libraries/registries/registries-mc18w43a-mc19w03c/src/main/resources/osl.registries.mixins.json b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/resources/osl.registries.mixins.json new file mode 100644 index 000000000..60e06d4c1 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc19w03c/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,24 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.BootstrapMixin", + "common.CrudeIncrementalIntIdentityHashMapMixin", + "common.DefaultedIdRegistryAccess", + "common.Id2ObjectBiMapMixin", + "common.IdRegistryMixin", + "common.MinecraftServerMixin", + "common.PlayerManagerMixin" + ], + "client": [ + "client.IntegratedServerMixin" + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/build.gradle b/libraries/registries/registries-mc19w04a-mc1.14.4/build.gradle new file mode 100644 index 000000000..0a350fdb3 --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/build.gradle @@ -0,0 +1 @@ +setUpModule(project) diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/gradle.properties b/libraries/registries/registries-mc19w04a-mc1.14.4/gradle.properties new file mode 100644 index 000000000..14d415739 --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/gradle.properties @@ -0,0 +1,5 @@ +min_mc_version = 19w04a +max_mc_version = 1.14.4 +minecraft_dependency = >=1.14-alpha.19.4.a <=1.14.4 + +minecraft_version = 1.14.4 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 new file mode 100644 index 000000000..87d5b78ad --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; + +/** + * Utility class containing commonly used registry keys (i.e. @linkplain + * ResourceKey resource keys} for registries), as well as factory methods + * for creating registry keys. + */ +public final class RegistryKeys { + + public static final ResourceKey> BLOCK = from("block"); + public static final ResourceKey> ITEM = from("item"); + + /** + * Constructs a registry key with the default namespace and the given identifier. + * + * @param the value type of the registry. + * @param identifier the identifier of the registry. + * @return the constructed registry key. + */ + public static ResourceKey> from(String identifier) { + return from(NamespacedIdentifiers.from(identifier)); + } + + /** + * Constructs a registry key with the given namespaced identifier. + * + * @param the value type of the registry. + * @param identifier the namespaced identifier of the registry. + * @return the constructed registry key. + */ + public static ResourceKey> from(NamespacedIdentifier identifier) { + return ResourceKeys.from(identifier); + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java new file mode 100644 index 000000000..544daace9 --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java @@ -0,0 +1,67 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import net.minecraft.util.Id2ObjectBiMap; + +/** + * An {@linkplain IdMapper} implementation for {@linkplain Id2ObjectBiMap}s + * where IDs are used as keys to the map. The values are moved from the old key + * (the old ID) to the new key (the new ID) within the same map. {@code null} is + * used as the default or "empty" value. + */ +public class Id2ObjectBiMapMapper implements IdMapper { + + public static Id2ObjectBiMapMapper of(Id2ObjectBiMap registry) { + return new Id2ObjectBiMapMapper(registry); + } + + private final Id2ObjectBiMap registry; + private final Id2ObjectBiMap backup; + + private boolean applied; + + @SuppressWarnings("unchecked") + private Id2ObjectBiMapMapper(Id2ObjectBiMap registry) { + this.registry = (Id2ObjectBiMap) registry; + this.backup = new Id2ObjectBiMap<>(registry.size()); + } + + /* + * unlike Registry, Id2ObjectBiMap allows duplicate values + * thus iterating over all values will not give you all id-value pairs! + */ + + @Override + public void apply(RegistryMappings mappings) { + this.backup.osl$registries$clear(); + + for (int id : this.registry.osl$registries$idSet()) { + this.backup.put(this.registry.get(id), id); + } + + this.registry.osl$registries$clear(); + + for (int oldId : this.backup.osl$registries$idSet()) { + Object value = this.backup.get(oldId); + int newId = mappings.remap(oldId); + + if (newId >= 0) { + this.registry.put(value, newId); + } + } + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + this.registry.osl$registries$clear(); + + for (int id : this.backup.osl$registries$idSet()) { + this.registry.put(this.backup.get(id), id); + } + } + + this.applied = false; + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java new file mode 100644 index 000000000..f6896b0bd --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,43 @@ +package net.ornithemc.osl.registries.impl; + +import net.minecraft.text.LiteralText; + +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.api.client.ClientPlayNetworking; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +public final class RegistriesEntrypoint implements ClientModInitializer { + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(Constants.OSL_REGISTRY_SYNC_CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesPacketSerializer.deserialize(buffer, RegistryMappingSource.REMOTE_SERVER); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.applyMappings(); + }); + } catch (RegistryMappingException e) { + RegistriesImpl.LOGGER.error("Unable to remap registries!", e); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.resetMappings(); + + if (context.networkHandler().getConnection().isConnected()) { + context.networkHandler().getConnection().disconnect(new LiteralText("Failed to remap registries: " + e.getMessage())); + } + }); + } + }); + ClientConnectionEvents.DISCONNECT.register(context -> { + if (!context.isServerLocal()) { + SyncedRegistriesImpl.undoMappings(); + } + }); + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java new file mode 100644 index 000000000..d7017be43 --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/access/Clearable.java @@ -0,0 +1,16 @@ +package net.ornithemc.osl.registries.impl.access; + +public interface Clearable { + + static void clear(Object o) { + if (o instanceof Clearable) { + ((Clearable) o).osl$registries$clear(); + } else { + throw new IllegalArgumentException("not clearable: " + o); + } + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess.java new file mode 100644 index 000000000..d0437d3ac --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.access; + +import it.unimi.dsi.fastutil.ints.IntSet; + +public interface Id2ObjectBiMapAccess { + + default IntSet osl$registries$idSet() { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java new file mode 100644 index 000000000..83f069aa5 --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/access/IdRegistryAccess.java @@ -0,0 +1,20 @@ +package net.ornithemc.osl.registries.impl.access; + +import net.minecraft.resource.Identifier; + +public interface IdRegistryAccess { + + default void osl$registries$setCallback(RegisterCallback callback) { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } + + interface RegisterCallback { + + void valueRegistered(int id, Identifier key, Object value); + + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java new file mode 100644 index 000000000..ea596a58c --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java @@ -0,0 +1,11 @@ +package net.ornithemc.osl.registries.impl.access; + +import java.io.IOException; + +public interface WorldStorageAccess { + + void osl$registries$loadRegistryMappings() throws IOException; + + void osl$registries$saveRegistryMappings() throws IOException; + +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java new file mode 100644 index 000000000..f574a096b --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java @@ -0,0 +1,49 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import java.io.IOException; + +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.sugar.Local; + +import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.util.crash.CrashException; +import net.minecraft.util.crash.CrashReport; +import net.minecraft.world.storage.AlphaWorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(IntegratedServer.class) +public class IntegratedServerMixin { + + @Inject( + method = "loadWorld", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/storage/AlphaWorldStorage;m_16306786()Lnet/minecraft/world/WorldData;" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci, @Local AlphaWorldStorage storage) { + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$loadRegistryMappings(); + } catch (IOException e) { + throw new CrashException(CrashReport.of(e, "Exception initializing level")); + } + } + } + + @Inject( + method = "shutdown", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$unmapRegistries(CallbackInfo ci) { + SyncedRegistriesImpl.undoMappings(); + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java new file mode 100644 index 000000000..8095bd5a7 --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,116 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.storage.AlphaWorldStorage; + +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesNbtSerializer; + +@Mixin(AlphaWorldStorage.class) +public class AlphaWorldStorageMixin implements WorldStorageAccess { + + @Shadow @Final + private String name; + + @Shadow + private File m_52081685() { return null; } + + @Override + public void osl$registries$loadRegistryMappings() throws IOException { + File dir = this.m_52081685(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + + if (!this.readRegistryMappings(file, false)) { + file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + if (!this.readRegistryMappings(file, true)) { + RegistriesImpl.LOGGER.debug("no registry mappings read for '" + this.name + "'"); + } + } + } + + @Unique + private boolean readRegistryMappings(File file, boolean throwOnException) throws IOException { + if (file.exists()) { + try (InputStream is = new FileInputStream(file)) { + NbtCompound nbt = NbtIo.readCompressed(is); + + SyncedRegistriesNbtSerializer.deserialize(nbt, RegistryMappingSource.WORLD_SAVE); + SyncedRegistriesImpl.applyMappings(); + + return true; + } catch (IOException e) { + if (throwOnException) { + throw new IOException("Unable to read registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("error while reading registry mappings for '" + this.name + "'", e); + } + } catch (RegistryMappingException e) { + if (throwOnException) { + throw new IOException("Invalid registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("invalid registry mappings for '" + this.name + "'", e); + } + } + } + + return false; + } + + @Override + public void osl$registries$saveRegistryMappings() throws IOException { + File dir = this.m_52081685(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + File tmp = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_tmp"); + File backup = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + this.writeRegistryMappings(file, tmp, backup); + } + + @Unique + private void writeRegistryMappings(File file, File newFile, File oldFile) throws IOException { + NbtCompound nbt = new NbtCompound(); + + try { + SyncedRegistriesNbtSerializer.serialize(nbt); + + try (OutputStream os = new FileOutputStream(newFile)) { + NbtIo.writeCompressed(nbt, os); + } + + if (oldFile.exists()) { + oldFile.delete(); + } + + file.renameTo(oldFile); + if (file.exists()) { + file.delete(); + } + + newFile.renameTo(file); + if (newFile.exists()) { + newFile.delete(); + } + } catch (IOException e) { + RegistriesImpl.LOGGER.warn("error while writing registry mappings for '" + this.name + "'", e); + } + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java new file mode 100644 index 000000000..7b6b88a17 --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.registries.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 net.minecraft.Bootstrap; +import net.minecraft.util.registry.Registry; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(Bootstrap.class) +public class BootstrapMixin { + + @Inject( + method = "init", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/util/registry/Registry;REGISTRY:Lnet/minecraft/unmapped/C_06803903;", + opcode = Opcodes.GETSTATIC + ) + ) + private static void osl$registries$initRegistries(CallbackInfo ci) { + // force registry loading (the targeted field access does the same) + Registry.REGISTRY.getClass(); + + RegistriesImpl.init(); + SyncedRegistriesImpl.init(); + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java new file mode 100644 index 000000000..773df9d09 --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Arrays; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; + +import net.ornithemc.osl.registries.impl.access.Clearable; + +@Mixin(CrudeIncrementalIntIdentityHashMap.class) +public class CrudeIncrementalIntIdentityHashMapMixin implements Clearable { + + @Shadow + private Object[] keys; + @Shadow + private Object[] byId; + + @Shadow + private int nextId; + @Shadow + private int size; + + @Override + public void osl$registries$clear() { + Arrays.fill(this.keys, null); + Arrays.fill(this.byId, null); + + this.nextId = 0; + this.size = 0; + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java new file mode 100644 index 000000000..79f753e2f --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java @@ -0,0 +1,15 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.DefaultedIdRegistry; + +@Mixin(DefaultedIdRegistry.class) +public interface DefaultedIdRegistryAccess { + + @Accessor("defaultId") + Identifier accessDefaultId(); + +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java new file mode 100644 index 000000000..3a3ce1078 --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java @@ -0,0 +1,59 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.IdentityHashMap; +import java.util.List; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; + +import net.minecraft.util.Id2ObjectBiMap; + +import net.ornithemc.osl.registries.impl.access.Clearable; +import net.ornithemc.osl.registries.impl.access.Id2ObjectBiMapAccess; + +@Mixin(Id2ObjectBiMap.class) +public class Id2ObjectBiMapMixin implements Id2ObjectBiMapAccess, Clearable { + + @Shadow @Final + private List values; + @Shadow @Final + private IdentityHashMap ids; + + @Shadow + private int nextId; + + @Unique + private final IntSet idSet = new IntOpenHashSet(); + + @Inject( + method = "put(Ljava/lang/Object;I)V", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$put(T value, int id, CallbackInfo ci) { + this.idSet.add(id); + } + + @Override + public IntSet osl$registries$idSet() { + return this.idSet; + } + + @Override + public void osl$registries$clear() { + this.values.clear(); + this.ids.clear(); + this.idSet.clear(); + + this.nextId = 0; + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java new file mode 100644 index 000000000..02a70e1be --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java @@ -0,0 +1,53 @@ +package net.ornithemc.osl.registries.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.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import com.google.common.collect.BiMap; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.registries.impl.access.Clearable; +import net.ornithemc.osl.registries.impl.access.IdRegistryAccess; + +@Mixin(IdRegistry.class) +public class IdRegistryMixin implements IdRegistryAccess, Clearable { + + @Shadow @Final + private CrudeIncrementalIntIdentityHashMap ids; + @Shadow @Final + private BiMap values; + + @Unique + private RegisterCallback callback; + + @Inject( + method = "m_26252208", + at = @At( + value = "RETURN" + ) + ) + private void osl$registries$register(int id, Identifier key, T value, CallbackInfoReturnable cir) { + if (this.callback != null) { + this.callback.valueRegistered(id, key, value); + } + } + + @Override + public void osl$registries$setCallback(RegisterCallback callback) { + this.callback = callback; + } + + @Override + public void osl$registries$clear() { + this.values.clear(); + Clearable.clear(this.ids); + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java new file mode 100644 index 000000000..c3908b99c --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/MinecraftServerMixin.java @@ -0,0 +1,64 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.IOException; + +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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.crash.CrashException; +import net.minecraft.util.crash.CrashReport; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.storage.AlphaWorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + + @Inject( + method = "loadWorld", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/storage/AlphaWorldStorage;m_16306786()Lnet/minecraft/world/WorldData;" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci, @Local AlphaWorldStorage storage) { + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$loadRegistryMappings(); + } catch (IOException e) { + throw new CrashException(CrashReport.of(e, "Exception initializing level")); + } + } + } + + @Inject( + method = "saveWorlds", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(CallbackInfoReturnable cir) { + @SuppressWarnings("resource") + MinecraftServer server = (MinecraftServer) (Object) this; + + ServerWorld overworld = server.getWorld(DimensionType.OVERWORLD); + AlphaWorldStorage storage = overworld.m_73575718(); + + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$saveRegistryMappings(); + } catch (IOException e) { + RegistriesImpl.LOGGER.error("Exception saving level", e); + } + } + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java new file mode 100644 index 000000000..01174aa6b --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.registries.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 com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerPlayNetworking; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final + private MinecraftServer server; + + @Inject( + method = "onLogin", + at = @At( + value = "NEW", + target = "net/minecraft/network/packet/s2c/play/LoginS2CPacket" + ) + ) + private void osl$idsync$syncRegistries(CallbackInfo ci, @Local ServerPlayerEntity player) { + if (this.server.isDedicated() || !this.server.getUsername().equals(player.getGameProfile().getName())) { + ServerPlayNetworking.sendNoCheck(player, Constants.OSL_REGISTRY_SYNC_CHANNEL, SyncedRegistriesPacketSerializer::serialize); + } + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java new file mode 100644 index 000000000..9cdf561fc --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java @@ -0,0 +1,19 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.util.registry.DefaultedIdRegistry; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public final class VanillaRegistries { + + public static Registry registerSimple(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return RegistriesImpl.register(key, WrappedIdRegistry.of(key, (IdRegistry) registry), () -> { }); + } + + public static DefaultedRegistry registerDefaulted(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return RegistriesImpl.register(key, WrappedDefaultedIdRegistry.of(key, (DefaultedIdRegistry) registry), () -> { }); + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java new file mode 100644 index 000000000..d1cf93ce7 --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java @@ -0,0 +1,25 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.util.registry.DefaultedIdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.impl.mixin.common.DefaultedIdRegistryAccess; + +public class WrappedDefaultedIdRegistry extends WrappedIdRegistry implements DefaultedRegistry { + + public static WrappedDefaultedIdRegistry of(ResourceKey> key, DefaultedIdRegistry registry) { + return new WrappedDefaultedIdRegistry<>(key.identifier(), registry); + } + + private WrappedDefaultedIdRegistry(NamespacedIdentifier identifier, DefaultedIdRegistry registry) { + super(identifier, registry); + } + + @Override + public NamespacedIdentifier getDefaultIdentifier() { + return this.serializeKey(((DefaultedIdRegistryAccess) this.registry).accessDefaultId()); + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java new file mode 100644 index 000000000..6d0df9147 --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java @@ -0,0 +1,133 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.Iterator; +import java.util.Set; +import java.util.stream.Collectors; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.ResourceKeys; + +public class WrappedIdRegistry implements ClearableRegistry { + + public static WrappedIdRegistry of(ResourceKey> key, IdRegistry registry) { + return new WrappedIdRegistry<>(key.identifier(), registry); + } + + final NamespacedIdentifier identifier; + final IdRegistry registry; + + private int nextId; + private boolean frozen; + + WrappedIdRegistry(NamespacedIdentifier identifier, IdRegistry registry) { + this.identifier = identifier; + this.registry = registry; + + this.registry.osl$registries$setCallback(this::valueRegistered); + } + + NamespacedIdentifier serializeKey(Identifier key) { + return key; + } + + Identifier deserializeKey(NamespacedIdentifier identifier) { + return identifier == null ? null : (identifier instanceof Identifier ? (Identifier) identifier : new Identifier(identifier.namespace(), identifier.identifier())); + } + + ResourceKey resourceKey(NamespacedIdentifier identifier) { + return identifier == null ? null : ResourceKeys.from(this.identifier, identifier); + } + + private void valueRegistered(int id, Identifier key, Object value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + + this.nextId = Math.max(this.nextId, id + 1); + } + + @Override + public V register(ResourceKey key, V value) { + return this.register(this.nextId, key, value); + } + + @Override + public V register(int id, ResourceKey key, V value) { + this.registry.m_26252208(id, this.deserializeKey(key.identifier()), value); + return value; + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } + + @Override + public T get(int id) { + return this.registry.get(id); + } + + @Override + public T get(ResourceKey key) { + Identifier k = this.deserializeKey(key.identifier()); + return this.registry.containsKey(k) ? this.registry.getOrDefault(k) : null; + } + + @Override + public T get(NamespacedIdentifier identifier) { + Identifier k = this.deserializeKey(identifier); + return this.registry.containsKey(k) ? this.registry.getOrDefault(k) : null; + } + + @Override + public int getId(T value) { + return this.registry.getId(value); + } + + @Override + public ResourceKey getKey(T value) { + return this.resourceKey(this.serializeKey(this.registry.getKey(value))); + } + + @Override + public NamespacedIdentifier getIdentifier(T value) { + return this.serializeKey(this.registry.getKey(value)); + } + + @Override + public Set> keySet() { + return this.registry.keySet().stream().map(this::serializeKey).map(this::resourceKey).collect(Collectors.toSet()); + } + + @Override + public Set identifierSet() { + return this.registry.keySet().stream().map(this::serializeKey).collect(Collectors.toSet()); + } + + @Override + public Iterator iterator() { + return this.registry.iterator(); + } + + @Override + public Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public void clear() { + this.registry.osl$registries$clear(); + + this.nextId = 0; + this.frozen = false; + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java new file mode 100644 index 000000000..b2b48ca34 --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java @@ -0,0 +1,78 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.minecraft.nbt.NbtCompound; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesNbtSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(NbtCompound nbt) throws IOException { + NbtCompound registriesNbt = new NbtCompound(); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt, SyncedRegistriesNbtSerializer::serialize); + registriesNbt.put(identifier.toString(), mappingsNbt); + } + + nbt.putInt(Constants.FORMAT_NBT_KEY, Constants.REGISTRY_MAPPINGS_FORMAT); + nbt.put(Constants.REGISTRIES_NBT_KEY, registriesNbt); + } + + public static void deserialize(NbtCompound nbt, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = nbt.getInt(Constants.FORMAT_NBT_KEY); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + NbtCompound registriesNbt = nbt.getCompound(Constants.REGISTRIES_NBT_KEY); + + for (String key : registriesNbt.getKeys()) { + NbtCompound mappingsNbt = registriesNbt.getCompound(key); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(key); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(mappingsNbt, SyncedRegistriesNbtSerializer::deserialize, source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(NbtCompound nbt, Object2IntMap mappings) throws IOException { + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } + + public static void deserialize(NbtCompound nbt, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + for (String key : nbt.getKeys()) { + mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java new file mode 100644 index 000000000..d21165816 --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java @@ -0,0 +1,81 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesPacketSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(Constants.REGISTRY_MAPPINGS_FORMAT); + buffer.writeVarInt(REGISTRIES.keySet().size()); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer, SyncedRegistriesPacketSerializer::serialize); + } + } + + public static void deserialize(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(buffer, SyncedRegistriesPacketSerializer::deserialize, source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(PacketBuffer buffer, Object2IntMap mappings) throws IOException { + buffer.writeVarInt(mappings.size()); + + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public static void deserialize(PacketBuffer buffer, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + mappings.put(identifier, id); + } + } +} diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/resources/fabric.mod.json b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..2eb436d43 --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/resources/fabric.mod.json @@ -0,0 +1,37 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc19w04a-mc1.14.4", + "environment": "*", + "entrypoints": { + "client-init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ] + }, + "mixins": [ + "osl.registries.mixins.json" + ], + "accessWidener": "osl.registries.classtweaker", + "depends": { + "fabricloader": "\u003e\u003d0.18.0", + "minecraft": "\u003e\u003d1.14-alpha.19.4.a \u003c\u003d1.14.4", + "osl-core": "\u003e\u003d0.8.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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0" + }, + "name": "OSL Registries", + "description": "Registries API and numerical ID synchronization.", + "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/registries/registries-mc19w04a-mc1.14.4/src/main/resources/osl.registries.classtweaker b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/resources/osl.registries.classtweaker new file mode 100644 index 000000000..9cbd4bc0c --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/resources/osl.registries.classtweaker @@ -0,0 +1,4 @@ +classTweaker v1 named + +inject-interface net/minecraft/util/Id2ObjectBiMap net/ornithemc/osl/registries/impl/access/Id2ObjectBiMapAccess +inject-interface net/minecraft/util/registry/IdRegistry net/ornithemc/osl/registries/impl/access/IdRegistryAccess diff --git a/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/resources/osl.registries.mixins.json b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/resources/osl.registries.mixins.json new file mode 100644 index 000000000..60e06d4c1 --- /dev/null +++ b/libraries/registries/registries-mc19w04a-mc1.14.4/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,24 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.BootstrapMixin", + "common.CrudeIncrementalIntIdentityHashMapMixin", + "common.DefaultedIdRegistryAccess", + "common.Id2ObjectBiMapMixin", + "common.IdRegistryMixin", + "common.MinecraftServerMixin", + "common.PlayerManagerMixin" + ], + "client": [ + "client.IntegratedServerMixin" + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/build.gradle b/libraries/registries/registries-mca1.0.1_01-mc12w17a/build.gradle new file mode 100644 index 000000000..0a350fdb3 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/build.gradle @@ -0,0 +1 @@ +setUpModule(project) diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/gradle.properties b/libraries/registries/registries-mca1.0.1_01-mc12w17a/gradle.properties new file mode 100644 index 000000000..07b542d0c --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/gradle.properties @@ -0,0 +1,8 @@ +min_mc_version = a1.0.1_01 +max_mc_version = 12w17a +minecraft_dependency = >=1.0.0-alpha.0.1 <=1.3-alpha.12.17.a + +minecraft_version = 1.2.5 +client_raven_build = 1 +client_nests_build = 10 +server_nests_build = 4 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 new file mode 100644 index 000000000..87d5b78ad --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; + +/** + * Utility class containing commonly used registry keys (i.e. @linkplain + * ResourceKey resource keys} for registries), as well as factory methods + * for creating registry keys. + */ +public final class RegistryKeys { + + public static final ResourceKey> BLOCK = from("block"); + public static final ResourceKey> ITEM = from("item"); + + /** + * Constructs a registry key with the default namespace and the given identifier. + * + * @param the value type of the registry. + * @param identifier the identifier of the registry. + * @return the constructed registry key. + */ + public static ResourceKey> from(String identifier) { + return from(NamespacedIdentifiers.from(identifier)); + } + + /** + * Constructs a registry key with the given namespaced identifier. + * + * @param the value type of the registry. + * @param identifier the namespaced identifier of the registry. + * @return the constructed registry key. + */ + public static ResourceKey> from(NamespacedIdentifier identifier) { + return ResourceKeys.from(identifier); + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/Bootstrap.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/Bootstrap.java new file mode 100644 index 000000000..c27f86c9c --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/Bootstrap.java @@ -0,0 +1,18 @@ +package net.ornithemc.osl.registries.impl; + +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +public final class Bootstrap { + + private static boolean initialized; + + public static void init() { + if (!initialized) { + initialized = true; + + RegistriesImpl.init(); + SyncedRegistriesImpl.init(); + } + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java new file mode 100644 index 000000000..76a2462af --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,42 @@ +package net.ornithemc.osl.registries.impl; + +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.api.client.ClientPlayNetworking; +import net.ornithemc.osl.registries.impl.mixin.client.ClientNetworkHandlerAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +public final class RegistriesEntrypoint implements ClientModInitializer { + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(Constants.OSL_REGISTRY_SYNC_CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesPacketSerializer.deserialize(buffer, RegistryMappingSource.REMOTE_SERVER); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.applyMappings(); + }); + } catch (RegistryMappingException e) { + RegistriesImpl.LOGGER.error("Unable to remap registries!", e); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.resetMappings(); + + if (!((ClientNetworkHandlerAccess) context.networkHandler()).accessDisconnected()) { + ((ClientNetworkHandlerAccess) context.networkHandler()).accessConnection().close("Failed to remap registries: " + e.getMessage()); + } + }); + } + }); + ClientConnectionEvents.DISCONNECT.register(context -> { + if (!context.isServerLocal()) { + SyncedRegistriesImpl.undoMappings(); + } + }); + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java new file mode 100644 index 000000000..35b3fe01f --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java @@ -0,0 +1,69 @@ +package net.ornithemc.osl.registries.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.fabricmc.api.EnvType; +import net.fabricmc.loader.api.FabricLoader; + +import net.ornithemc.osl.core.impl.util.MinecraftVersion; + +public class RegistriesMixinPlugin implements IMixinConfigPlugin { + + private static final boolean OLD_WORLD_FORMAT = MinecraftVersion.resolve().compareTo("b1.3") < 0; + private static final boolean DIMENSIONS_EXIST = MinecraftVersion.resolve().compareTo(FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT ? "a1.2.0" : "a0.2.2") >= 0; + + @Override + public void onLoad(String mixinPackage) { + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if ("net.ornithemc.osl.registries.impl.mixin.client.MinecraftMixinOld".equals(mixinClassName) + || "net.ornithemc.osl.registries.impl.mixin.client.WorldAccessOld".equals(mixinClassName) + || "net.ornithemc.osl.registries.impl.mixin.server.MinecraftServerMixinOld".equals(mixinClassName)) { + return OLD_WORLD_FORMAT; + } + if ("net.ornithemc.osl.registries.impl.mixin.common.AlphaWorldStorageMixin".equals(mixinClassName) + || "net.ornithemc.osl.registries.impl.mixin.client.WorldAccessNew".equals(mixinClassName) + || "net.ornithemc.osl.registries.impl.mixin.client.MinecraftMixinNew".equals(mixinClassName) + || "net.ornithemc.osl.registries.impl.mixin.server.MinecraftServerMixinNew".equals(mixinClassName)) { + return !OLD_WORLD_FORMAT; + } + if ("net.ornithemc.osl.registries.impl.mixin.common.WorldMixinNew".equals(mixinClassName)) { + return OLD_WORLD_FORMAT && DIMENSIONS_EXIST; + } + if ("net.ornithemc.osl.registries.impl.mixin.common.WorldMixinOld".equals(mixinClassName)) { + return OLD_WORLD_FORMAT && !DIMENSIONS_EXIST; + } + + 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/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java new file mode 100644 index 000000000..ea596a58c --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/access/WorldStorageAccess.java @@ -0,0 +1,11 @@ +package net.ornithemc.osl.registries.impl.access; + +import java.io.IOException; + +public interface WorldStorageAccess { + + void osl$registries$loadRegistryMappings() throws IOException; + + void osl$registries$saveRegistryMappings() throws IOException; + +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/ClientNetworkHandlerAccess.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..3bf29cf9b --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/ClientNetworkHandlerAccess.java @@ -0,0 +1,18 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.client.network.handler.ClientNetworkHandler; +import net.minecraft.network.Connection; + +@Mixin(ClientNetworkHandler.class) +public interface ClientNetworkHandlerAccess { + + @Accessor("connection") + Connection accessConnection(); + + @Accessor("disconnected") + boolean accessDisconnected(); + +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/MinecraftMixin.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/MinecraftMixin.java new file mode 100644 index 000000000..107f853f6 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/MinecraftMixin.java @@ -0,0 +1,27 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +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.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; + +import net.ornithemc.osl.registries.impl.Bootstrap; + +@Mixin(Minecraft.class) +public class MinecraftMixin { + + @Inject( + method = "", + at = @At( + value = "INVOKE", + target = "Ljava/lang/Object;()V", + shift = Shift.AFTER + ) + ) + private void osl$registries$bootstrap(CallbackInfo ci) { + Bootstrap.init(); + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/MinecraftMixinNew.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/MinecraftMixinNew.java new file mode 100644 index 000000000..b446b6002 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/MinecraftMixinNew.java @@ -0,0 +1,65 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import java.io.IOException; + +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.At.Shift; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.client.Minecraft; +import net.minecraft.world.World; +import net.minecraft.world.storage.WorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +@Mixin(Minecraft.class) +public class MinecraftMixinNew { + + @Shadow + private World world; + + @Inject( + method = "startGame", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/storage/WorldStorageSource;get(Ljava/lang/String;Z)Lnet/minecraft/world/storage/WorldStorage;", + shift = Shift.BY, + by = 2 + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci, @Local WorldStorage storage) { + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$loadRegistryMappings(); + } catch (IOException e) { + throw new RuntimeException("Exception initializing level", e); + } + } + } + + @Inject( + method = "setWorld(Lnet/minecraft/world/World;Ljava/lang/String;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(World world, String message, CallbackInfo ci) { + if (this.world != null && !this.world.isMultiplayer && world == null) { + WorldStorage storage = ((WorldAccessNew) this.world).accessStorage(); + + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$saveRegistryMappings(); + } catch (IOException e) { + RegistriesImpl.LOGGER.error("Exception saving level", e); + } + } + } + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/MinecraftMixinOld.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/MinecraftMixinOld.java new file mode 100644 index 000000000..8ceda3e22 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/MinecraftMixinOld.java @@ -0,0 +1,41 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import java.io.File; +import java.io.IOException; + +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.client.Minecraft; +import net.minecraft.world.World; + +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingStorage; + +@Mixin(Minecraft.class) +public class MinecraftMixinOld { + + @Shadow + private World world; + + @Inject( + method = "setWorld(Lnet/minecraft/world/World;Ljava/lang/String;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(World world, String message, CallbackInfo ci) { + if (this.world != null && !this.world.isMultiplayer && world == null) { + File dir = ((WorldAccessOld) this.world).accessSaveDirectory(); + + try { + RegistryMappingStorage.saveRegistryMappings(dir); + } catch (IOException e) { + RegistriesImpl.LOGGER.error("Exception saving level", e); + } + } + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/WorldAccessNew.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/WorldAccessNew.java new file mode 100644 index 000000000..9bb380bc2 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/WorldAccessNew.java @@ -0,0 +1,15 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.world.World; +import net.minecraft.world.storage.WorldStorage; + +@Mixin(World.class) +public interface WorldAccessNew { + + @Accessor("storage") + WorldStorage accessStorage(); + +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/WorldAccessOld.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/WorldAccessOld.java new file mode 100644 index 000000000..ef604fa3a --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/WorldAccessOld.java @@ -0,0 +1,16 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import java.io.File; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.world.World; + +@Mixin(World.class) +public interface WorldAccessOld { + + @Accessor("f_14667040") + File accessSaveDirectory(); + +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java new file mode 100644 index 000000000..3dab6adbb --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,29 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.File; +import java.io.IOException; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.world.storage.AlphaWorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingStorage; + +@Mixin(AlphaWorldStorage.class) +public class AlphaWorldStorageMixin implements WorldStorageAccess { + + @Shadow + private File getDirectory() { return null; } + + @Override + public void osl$registries$loadRegistryMappings() throws IOException { + RegistryMappingStorage.loadRegistryMappings(this.getDirectory()); + } + + @Override + public void osl$registries$saveRegistryMappings() throws IOException { + RegistryMappingStorage.saveRegistryMappings(this.getDirectory()); + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/NbtCompoundAccess.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/NbtCompoundAccess.java new file mode 100644 index 000000000..91ac96618 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/NbtCompoundAccess.java @@ -0,0 +1,17 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Map; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; + +@Mixin(NbtCompound.class) +public interface NbtCompoundAccess { + + @Accessor("elements") + Map accessElements(); + +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/WorldMixinNew.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/WorldMixinNew.java new file mode 100644 index 000000000..72d72f7ab --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/WorldMixinNew.java @@ -0,0 +1,36 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.File; +import java.io.IOException; + +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.world.World; + +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingStorage; + +@Mixin(World.class) +public class WorldMixinNew { + + @Shadow + private File f_14667040; // saveDir + + @Inject( + method = "(Ljava/io/File;Ljava/lang/String;JLnet/minecraft/unmapped/C_90532916;)V", + at = @At( + value = "CONSTANT", + args = "stringValue=level.dat" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci) { + try { + RegistryMappingStorage.loadRegistryMappings(this.f_14667040); + } catch (IOException e) { + throw new RuntimeException("Exception initializing level", e); + } + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/WorldMixinOld.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/WorldMixinOld.java new file mode 100644 index 000000000..0b2f19b4f --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/WorldMixinOld.java @@ -0,0 +1,36 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.File; +import java.io.IOException; + +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.world.World; + +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingStorage; + +@Mixin(World.class) +public class WorldMixinOld { + + @Shadow + private File f_14667040; // saveDir + + @Inject( + method = "(Ljava/io/File;Ljava/lang/String;J)V", + at = @At( + value = "CONSTANT", + args = "stringValue=level.dat" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci) { + try { + RegistryMappingStorage.loadRegistryMappings(this.f_14667040); + } catch (IOException e) { + throw new RuntimeException("Exception initializing level", e); + } + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/MinecraftServerMixin.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/MinecraftServerMixin.java new file mode 100644 index 000000000..879f51ea3 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/MinecraftServerMixin.java @@ -0,0 +1,27 @@ +package net.ornithemc.osl.registries.impl.mixin.server; + +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.server.MinecraftServer; + +import net.ornithemc.osl.registries.impl.Bootstrap; + +@Mixin( + value = MinecraftServer.class, + priority = 1001 // make sure entrypoints mixin is applied first +) +public class MinecraftServerMixin { + + @Inject( + method = "main", + at = @At( + value = "HEAD" + ) + ) + private static void osl$registries$bootstrap(CallbackInfo ci) { + Bootstrap.init(); + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/MinecraftServerMixinNew.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/MinecraftServerMixinNew.java new file mode 100644 index 000000000..089e27580 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/MinecraftServerMixinNew.java @@ -0,0 +1,61 @@ +package net.ornithemc.osl.registries.impl.mixin.server; + +import java.io.IOException; + +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 com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.storage.WorldStorage; + +import net.ornithemc.osl.registries.impl.access.WorldStorageAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixinNew { + + @Shadow + private ServerWorld[] worlds; + + @Inject( + method = "loadWorld", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/storage/WorldStorage;loadData()Lnet/minecraft/world/WorldData;" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfo ci, @Local WorldStorage storage) { + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$loadRegistryMappings(); + } catch (IOException e) { + throw new RuntimeException("Exception initializing level", e); + } + } + } + + @Inject( + method = "saveWorlds", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(CallbackInfo ci) { + ServerWorld overworld = this.worlds[0]; + WorldStorage storage = overworld.getStorage(); + + if (storage instanceof WorldStorageAccess) { + try { + ((WorldStorageAccess) storage).osl$registries$saveRegistryMappings(); + } catch (IOException e) { + RegistriesImpl.LOGGER.error("Exception saving level", e); + } + } + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/MinecraftServerMixinOld.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/MinecraftServerMixinOld.java new file mode 100644 index 000000000..c207a2e7e --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/MinecraftServerMixinOld.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.registries.impl.mixin.server; + +import java.io.File; +import java.io.IOException; + +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.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; + +import net.ornithemc.osl.registries.impl.mixin.client.WorldAccessOld; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingStorage; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixinOld { + + @Shadow + private ServerWorld f_58488472; + + @Inject( + method = "saveWorlds", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(CallbackInfo ci) { + File dir = ((WorldAccessOld) this.f_58488472).accessSaveDirectory(); + + try { + RegistryMappingStorage.saveRegistryMappings(dir); + } catch (IOException e) { + RegistriesImpl.LOGGER.error("Exception saving level", e); + } + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/ServerLoginNetworkHandlerMixin.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/ServerLoginNetworkHandlerMixin.java new file mode 100644 index 000000000..cc2efa07e --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/ServerLoginNetworkHandlerMixin.java @@ -0,0 +1,30 @@ +package net.ornithemc.osl.registries.impl.mixin.server; + +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.sugar.Local; + +import net.minecraft.server.entity.mob.player.ServerPlayerEntity; +import net.minecraft.server.network.handler.ServerLoginNetworkHandler; + +import net.ornithemc.osl.networking.api.server.ServerPlayNetworking; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +@Mixin(ServerLoginNetworkHandler.class) +public class ServerLoginNetworkHandlerMixin { + + @Inject( + method = "acceptLogin", + at = @At( + value = "NEW", + target = "net/minecraft/network/packet/LoginPacket" + ) + ) + private void osl$idsync$syncRegistries(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerPlayNetworking.sendNoCheck(player, Constants.OSL_REGISTRY_SYNC_CHANNEL, SyncedRegistriesPacketSerializer::serialize); + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMappingStorage.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMappingStorage.java new file mode 100644 index 000000000..0deac4414 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMappingStorage.java @@ -0,0 +1,93 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtIo; + +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +public final class RegistryMappingStorage { + + public static void loadRegistryMappings(File dir) throws IOException { + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + + if (!readRegistryMappings(dir, file, false)) { + file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + if (!readRegistryMappings(dir, file, true)) { + RegistriesImpl.LOGGER.debug("no registry mappings read for '" + dir.getName() + "'"); + } + } + } + + private static boolean readRegistryMappings(File dir, File file, boolean throwOnException) throws IOException { + if (file.exists()) { + try (InputStream is = new FileInputStream(file)) { + NbtCompound nbt = NbtIo.readCompressed(is); + + SyncedRegistriesNbtSerializer.deserialize(nbt, RegistryMappingSource.WORLD_SAVE); + SyncedRegistriesImpl.applyMappings(); + + return true; + } catch (IOException e) { + if (throwOnException) { + throw new IOException("Unable to read registry mappings for '" + dir.getName() + "'", e); + } else { + RegistriesImpl.LOGGER.warn("error while reading registry mappings for '" + dir.getName() + "'", e); + } + } catch (RegistryMappingException e) { + if (throwOnException) { + throw new IOException("Invalid registry mappings for '" + dir.getName() + "'", e); + } else { + RegistriesImpl.LOGGER.warn("invalid registry mappings for '" + dir.getName() + "'", e); + } + } + } + + return false; + } + + public static void saveRegistryMappings(File dir) throws IOException { + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + File tmp = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_tmp"); + File backup = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + writeRegistryMappings(dir, file, tmp, backup); + } + + private static void writeRegistryMappings(File dir, File file, File newFile, File oldFile) throws IOException { + NbtCompound nbt = new NbtCompound(); + + try { + SyncedRegistriesNbtSerializer.serialize(nbt); + + try (OutputStream os = new FileOutputStream(newFile)) { + NbtIo.writeCompressed(nbt, os); + } + + if (oldFile.exists()) { + oldFile.delete(); + } + + file.renameTo(oldFile); + if (file.exists()) { + file.delete(); + } + + newFile.renameTo(file); + if (newFile.exists()) { + newFile.delete(); + } + } catch (IOException e) { + RegistriesImpl.LOGGER.warn("error while writing registry mappings for '" + dir.getName() + "'", e); + } + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java new file mode 100644 index 000000000..131111816 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java @@ -0,0 +1,79 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.minecraft.nbt.NbtCompound; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.mixin.common.NbtCompoundAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesNbtSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(NbtCompound nbt) throws IOException { + NbtCompound registriesNbt = new NbtCompound(); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt, SyncedRegistriesNbtSerializer::serialize); + registriesNbt.put(identifier.toString(), mappingsNbt); + } + + nbt.putInt(Constants.FORMAT_NBT_KEY, Constants.REGISTRY_MAPPINGS_FORMAT); + nbt.put(Constants.REGISTRIES_NBT_KEY, registriesNbt); + } + + public static void deserialize(NbtCompound nbt, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = nbt.getInt(Constants.FORMAT_NBT_KEY); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + NbtCompound registriesNbt = nbt.getCompound(Constants.REGISTRIES_NBT_KEY); + + for (String key : ((NbtCompoundAccess) registriesNbt).accessElements().keySet()) { + NbtCompound mappingsNbt = registriesNbt.getCompound(key); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(key); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(mappingsNbt, SyncedRegistriesNbtSerializer::deserialize, source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(NbtCompound nbt, Object2IntMap mappings) throws IOException { + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } + + public static void deserialize(NbtCompound nbt, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + for (String key : ((NbtCompoundAccess) nbt).accessElements().keySet()) { + mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java new file mode 100644 index 000000000..d21165816 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java @@ -0,0 +1,81 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesPacketSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(Constants.REGISTRY_MAPPINGS_FORMAT); + buffer.writeVarInt(REGISTRIES.keySet().size()); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer, SyncedRegistriesPacketSerializer::serialize); + } + } + + public static void deserialize(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(buffer, SyncedRegistriesPacketSerializer::deserialize, source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(PacketBuffer buffer, Object2IntMap mappings) throws IOException { + buffer.writeVarInt(mappings.size()); + + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public static void deserialize(PacketBuffer buffer, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + mappings.put(identifier, id); + } + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/resources/fabric.mod.json b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..cbf3a4cd3 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/resources/fabric.mod.json @@ -0,0 +1,36 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mca1.0.1_01-mc12w17a", + "environment": "*", + "entrypoints": { + "client-init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ] + }, + "mixins": [ + "osl.registries.mixins.json" + ], + "depends": { + "fabricloader": "\u003e\u003d0.18.0", + "minecraft": "\u003e\u003d1.0.0-alpha.0.1 \u003c\u003d1.3-alpha.12.17.a", + "osl-core": "\u003e\u003d0.8.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.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0" + }, + "name": "OSL Registries", + "description": "Registries API and numerical ID synchronization.", + "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/registries/registries-mca1.0.1_01-mc12w17a/src/main/resources/osl.registries.mixins.json b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/resources/osl.registries.mixins.json new file mode 100644 index 000000000..c6589f9da --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc12w17a/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,31 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "plugin": "net.ornithemc.osl.registries.impl.RegistriesMixinPlugin", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.NbtCompoundAccess", + "common.WorldMixinNew", + "common.WorldMixinOld" + ], + "client": [ + "client.ClientNetworkHandlerAccess", + "client.MinecraftMixin", + "client.MinecraftMixinNew", + "client.MinecraftMixinOld", + "client.WorldAccessNew", + "client.WorldAccessOld" + ], + "server": [ + "server.MinecraftServerMixin", + "server.MinecraftServerMixinNew", + "server.MinecraftServerMixinOld", + "server.ServerLoginNetworkHandlerMixin" + ], + "injectors": { + "defaultRequire": 1, + "maxShiftBy": 2 + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/RegistryEvents.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/RegistryEvents.java new file mode 100644 index 000000000..9d8291886 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/RegistryEvents.java @@ -0,0 +1,31 @@ +package net.ornithemc.osl.registries.api; + +import net.ornithemc.osl.core.api.events.Event; + +/** + * Events related to registries. + */ +public final class RegistryEvents { + + /** + * This event is invoked on game start-up, after registries have been loaded, + * but before the bootstraps are run and the registries are frozen. + * Note that bootstraps may run before this point, if they are triggered by + * class loading. If you wish to hook into a particular registry's bootstrap, + * a Mixin injector is required. + * + *

+ * Callbacks to this event should be registered in your mod's entrypoint, + * and can be done as follows: + * + *

+	 * {@code
+	 * RegistryEvents.BOOTSTRAP_REGISTRIES.register(() -> {
+	 * 	...
+	 * });
+	 * }
+	 * 
+ */ + public static final Event BOOTSTRAP_REGISTRIES = Event.runnable(); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/DefaultedRegistry.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/DefaultedRegistry.java new file mode 100644 index 000000000..59cf51a02 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/DefaultedRegistry.java @@ -0,0 +1,24 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; + +/** + * A defaulted registry has a default value. If a value is requested from this + * registry but no mapping for the given ID, {@linkplain NamespacedIdentifier + * namespaced identifier} or {@linkplain ResourceKey resource key} is found, the + * default value is returned. + *
Likewise, if the ID, namespaced identifier, or resource key of a value + * is requested, but no mapping is found, that of the default value is returned. + * + * @param the value type. + * @see Registry + */ +public interface DefaultedRegistry extends Registry { + + /** + * @return the {@linkplain NamespacedIdentifier} namespaced identifier that + * uniquely identifies the default value. + */ + NamespacedIdentifier getDefaultIdentifier(); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/IdMap.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/IdMap.java new file mode 100644 index 000000000..282597328 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/IdMap.java @@ -0,0 +1,107 @@ +package net.ornithemc.osl.registries.api.registry; + +import java.util.Iterator; + +import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; +import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; +import it.unimi.dsi.fastutil.objects.Reference2IntMap; +import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; + +/** + * A simple bidirectional map for assigning numerical IDs to objects. IDs can be + * assigned manually through {@linkplain #put(T, int)} or automatically through + * {@link #put(T)}. The latter method will assign an ID one higher than the + * largest ID already in use. + * + *

+ * IDs are java {@code int}s and cannot be negative. ID uniqueness is guaranteed + * but value uniqueness is not. For this reason, the {@link #getId(T)} may + * return any of the IDs mapped to the given value. + * + * @param the value type. + */ +public final class IdMap implements Iterable { + + private final Int2ReferenceMap values; + private final Reference2IntMap ids; + + private int nextId = 0; + + public IdMap() { + this.values = new Int2ReferenceOpenHashMap<>(); + this.ids = new Reference2IntOpenHashMap<>(); + + this.ids.defaultReturnValue(-1); + } + + /** + * Adds the given value to the map with the next available ID. This ID is one + * higher than the largest ID already in use. + * + * @param value the value to add to the map. + * @return the value. + */ + public T put(T value) { + return this.put(value, this.nextId); + } + + /** + * Adds the given value to the map with the given ID. + * + * @param value the value to add to the map. + * @param id the ID to assign to the value. + * @return the value + */ + public T put(T value, int id) { + if (id < 0) { + throw new IllegalArgumentException("invalid ID " + id + " (must be >= 0)"); + } + + this.values.put(id, value); + this.ids.put(value, id); + + this.nextId = Math.max(this.nextId, id + 1); + + return value; + } + + /** + * Returns the ID assigned to the given value. Since value uniqueness is not + * guaranteed, the given value could appear multiple times, and this method may + * return any one of the IDs assigned to it. + * + * @return the ID assigned to the given value. + */ + public int getId(T value) { + return this.ids.getInt(value); + } + + /** + * @return the value assigned to the given ID. + */ + public T get(int id) { + return this.values.get(id); + } + + /** + * @return whether this map contains the given value. + */ + public boolean has(T value) { + return this.ids.containsKey(value); + } + + @Override + public Iterator iterator() { + return this.values.values().iterator(); + } + + /** + * Clears all values and IDs from this map. + */ + public void clear() { + this.values.clear(); + this.ids.clear(); + + this.nextId = 0; + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/Registries.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/Registries.java new file mode 100644 index 000000000..8072f516a --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/Registries.java @@ -0,0 +1,55 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +/** + * Utility class with public access to the root registry and methods for + * creating and registering registries. + * + * @see Registry + */ +public final class Registries { + + /** + * The root registry that holds references to all registered registries. + */ + public static final Registry> REGISTRY = RegistriesImpl.REGISTRY; + + /** + * @param the value type of the registry. + * @param key the resource key that identifies the registry. + * @return the registry identified by the given resource key. + */ + public static Registry get(ResourceKey> key) { + return RegistriesImpl.get(key); + } + + /** + * @param the value type of the registry. + * @param key the resource key that identifies the registry. + * @param bootstrap the callback for bootstrapping the registry. + * @return the registry. + * + * @see Registry + * @see Registry.Bootstrap + */ + public static Registry registerSimple(ResourceKey> key, Registry.Bootstrap bootstrap) { + return RegistriesImpl.registerSimple(key, bootstrap); + } + + /** + * @param the value type of the registry. + * @param key the resource key that identifies the registry. + * @param defaultIdentifier the namespaced identifier of the default value of the registry. + * @param bootstrap the callback for bootstrapping the registry. + * @return the registry. + * + * @see Registry + * @see Registry.Bootstrap + * @see DefaultedRegistry + */ + public static DefaultedRegistry registerDefaulted(ResourceKey> key, NamespacedIdentifier defaultIdentifier, Registry.Bootstrap bootstrap) { + return RegistriesImpl.registerDefaulted(key, defaultIdentifier, bootstrap); + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/Registry.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/Registry.java new file mode 100644 index 000000000..1fd42eb4c --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/Registry.java @@ -0,0 +1,184 @@ +package net.ornithemc.osl.registries.api.registry; + +import java.util.Set; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +/** + * Registries are used to keep track of in-game resources. A registry is assumed + * to hold all known values of a type (e.g. all known blocks), and each value is + * assigned a unique numerical ID as well as a unique + * {@linkplain NamespacedIdentifier namespaced identifier}. Because of this, + * registries play an important role in serialization and, consequently, in + * server-client communication and world save formats. + * + *

+ * Examples of registries are those for blocks, items, entity types, biomes, + * painting motives, stats, and enchantments. Registries themselves are also + * registered to a registry (see {@linkplain Registries#REGISTRY}). + * + * @param the value type. + */ +public interface Registry extends Iterable { + + /** + * @return the namespaced identifier that uniquely identifies this registry. + */ + NamespacedIdentifier identifier(); + + /** + * @return the value assigned to the given ID. + */ + T get(int id); + + /** + * @return the value mapped to the given resource key. + */ + T get(ResourceKey key); + + /** + * @return the value mapped to the given namespaced identifier. + */ + T get(NamespacedIdentifier identifier); + + /** + * @return the ID mapped to the given value. + */ + int getId(T value); + + /** + * @return the resource key mapped to the given value. + */ + ResourceKey getKey(T value); + + /** + * @return the namespaced identifier mapped to the given value. + */ + NamespacedIdentifier getIdentifier(T value); + + /** + * @return a set containing the resource keys of all values in this registry. + */ + Set> keySet(); + + /** + * @return a set containing the namespaced identifiers of all values in this registry. + */ + Set identifierSet(); + + /** + * Freezes this registry, disallowing any changes to be written to it. + * + * @return this registry. + */ + Registry freeze(); + + /** + * Helper method for registering a mapping to the given registry. + * + * @param the value type of the registry. + * @param the value type of the value to be registered. + * @param registry the registry to register the value to. + * @param key the resource key that uniquely identifies the value. + * @param value the value to be registered. + * @return the registered value. + */ + static V register(Registry registry, ResourceKey key, V value) { + return RegistriesImpl.registerMapping(registry, key, value); + } + + /** + * Helper method for registering a mapping to the given registry. + * + * @param the value type of the registry. + * @param the value type of the value to be registered. + * @param registry the registry to register the value to. + * @param identifier the namespaced identifier that uniquely identifies the value. + * @param value the value to be registered. + * @return the registered value. + */ + static V register(Registry registry, NamespacedIdentifier identifier, V value) { + return RegistriesImpl.registerMapping(registry, identifier, value); + } + + /** + * Helper method for registering a mapping to the given registry. + * + * @param the value type of the registry. + * @param the value type of the value to be registered. + * @param registry the registry to register the value to. + * @param id the ID that uniquely identifies the value. + * @param key the resource key that uniquely identifies the value. + * @param value the value to be registered. + * @return the registered value. + * + * @deprecated use {@link #register(Registry, ResourceKey, Object)} instead. + */ + @Deprecated + static V register(Registry registry, int id, ResourceKey key, V value) { + return RegistriesImpl.registerMapping(registry, id, key, value); + } + + /** + * Helper method for registering a mapping to the given registry. + * + * @param the value type of the registry. + * @param the value type of the value to be registered. + * @param registry the registry to register the value to. + * @param id the ID that uniquely identifies the value. + * @param identifier the namespaced identifier that uniquely identifies the value. + * @param value the value to be registered. + * @return the registered value. + * + * @deprecated use {@link #register(Registry, NamespacedIdentifier, Object)} instead. + */ + @Deprecated + static V register(Registry registry, int id, NamespacedIdentifier identifier, V value) { + return RegistriesImpl.registerMapping(registry, id, identifier, value); + } + + /** + * A registry bootstrap is a callback to populate a registry's contents. It is + * called upon game start-up, just before the registries are frozen. That makes + * this bootstrap the last chance for values to be registered to the registry. + * The registry may be populated earlier than this bootstrap, though, it is + * simply a utility. You may bootstrap your registry in any other way at any + * other point so long as it's before the registry freeze. + * + *

+ * A common pattern for registry bootstrapping is to use a separate class to + * hold the registry contents and populate the registry in its static + * initializer. Loading that class is then the trigger for bootstrapping the + * registry. An example is shown below. + * + *

+	 * {@code
+	 * public class ExampleRegistries {
+	 * 
+	 * 	// Note the method reference to CookieRecipes.init()!
+	 * 	public static final Registry COOKIE_RECIPE = Registries.registerSimple(REGISTRY_KEY, CookieRecipes::init);
+	 * 
+	 * }
+	 * 
+	 * public class CookieRecipes {
+	 * 
+	 * 	public static final CookieRecipe CHOCOLATE_CHIP = Registry.register(ExampleRegistries.COOKIE_RECIPE, NamespacedIdentifiers.from("example", "chocolate_chip"), new ChocolateChipCookieRecipe());
+	 * 
+	 * 	public static void init() {
+	 * 		// this method is the trigger to load the class
+	 * 		// the static initializer handles populating the registry
+	 * 	}
+	 * }
+	 * }
+	 * 
+ */ + interface Bootstrap { + + /** + * Bootstrap the registry, ensuring all its contents are created and registered. + */ + void init(); + + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/ResourceKey.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/ResourceKey.java new file mode 100644 index 000000000..03f85cd0e --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/ResourceKey.java @@ -0,0 +1,23 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; + +/** + * A resource key uniquely identifies a registered object. + * + * @param the value type of the registry. + * @see Registry + */ +public interface ResourceKey { + + /** + * @return the {@linkplain NamespacedIdentifier identifier} that uniquely identifies the registry. + */ + NamespacedIdentifier registry(); + + /** + * @return the {@linkplain NamespacedIdentifier identifier} that uniquely identifies value within the registry. + */ + NamespacedIdentifier identifier(); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/ResourceKeys.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/ResourceKeys.java new file mode 100644 index 000000000..fdb5cabf3 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/ResourceKeys.java @@ -0,0 +1,45 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.impl.registry.ResourceKeysImpl; + +/** + * A utility class for creating {@linkplain ResourceKey resource keys}. + */ +public final class ResourceKeys { + + /** + * Creates a resource key for a registry with the given namespaced identifier. + * + * @param the value type of the registry. + * @param identifier the identifier that uniquely identifies the registry. + * @return the resource key. + */ + public static ResourceKey from(NamespacedIdentifier identifier) { + return ResourceKeysImpl.from(identifier); + } + + /** + * Creates a resource key for a registry value with the given namespaced identifier. + * + * @param the value type of the registry. + * @param registry the resource key that uniquely identifies the registry. + * @param identifier the namespaced identifier that uniquely identifies the value. + * @return the resource key. + */ + public static ResourceKey from(ResourceKey> registry, NamespacedIdentifier identifier) { + return ResourceKeysImpl.from(registry.identifier(), identifier); + } + + /** + * Creates a resource key for a registry value with the given namespaced identifier. + * + * @param the value type of the registry. + * @param registry the namespaced identifier that uniquely identifies the registry. + * @param identifier the namespaced identifier that uniquely identifies the value. + * @return the resource key. + */ + public static ResourceKey from(NamespacedIdentifier registry, NamespacedIdentifier identifier) { + return ResourceKeysImpl.from(registry, identifier); + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/SyncedRegistries.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/SyncedRegistries.java new file mode 100644 index 000000000..6fe16420e --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/SyncedRegistries.java @@ -0,0 +1,77 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.sync.IdFixer; +import net.ornithemc.osl.registries.api.registry.sync.IdMapper; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +/** + * Utility class that serves as the public API for Registry Sync. Registry Sync + * is an important part of modding new content into the game. It ensures that + * the client and server agree on what content is present and how to serialize + * it. It is also responsible for synchronizing content across game sessions. + * + *

+ * The reason this is necessary is that the game uses numerical IDs to serialize + * content. This makes serialization for efficient, reducing network traffic and + * world save size. The issue is that these IDs are automatically generated, + * usually based on the order in which content is registered. This means that + * the IDs for mod content is dependent on the mods list and the mod loading + * order. If these are different between the server and client, or across game + * sessions, it can lead to bugs or even crashes and corrupted world saves. + * + *

+ * To prevent these issues, the Registry Sync API takes on the responsibility of + * synchronizing registry data between the client and server and across game + * sessions. This is done by remapping the numerical IDs of registry contents, + * and fixing up any resources that depend on these numerical IDs. + * + *

+ * Registries are not synchronized by default, and must be registered to do so. + * The API also accepts custom ID mappers and fixers for remapping other + * resources, such as arrays, lists,maps that use the numerical IDs as indices + * or keys, and fixing up other objects that store the numerical IDs. + * + * @see IdMapper + * @see IdFixer + */ +public final class SyncedRegistries { + + /** + * Registers the registry identified by the given {@linkplain ResourceKey + * resource key} to be synchronized between the client and server and across + * game sessions. A registry mapper for the registry will automatically be + * registered as well. + */ + public static void register(ResourceKey> registry) { + SyncedRegistriesImpl.register(registry); + } + + /** + * Registers the given ID mapper to the specified synchronized registry with + * the given {@linkplain NamespacedIdentifier} namespaced identifier. + * + * @param registry the {@linkplain ResourceKey resource key} that identifies + * the registry. + * @param identifier the {@linkplain NamespacedIdentifier} identifier for the + * ID mapper. + * @param mapper the ID mapper to be registered. + */ + public static void registerMapper(ResourceKey> registry, NamespacedIdentifier identifier, IdMapper mapper) { + SyncedRegistriesImpl.registerMapper(registry, identifier, mapper); + } + + /** + * Registers the given ID fixer to the specified synchronized registry with + * the given {@linkplain NamespacedIdentifier} namespaced identifier. + * + * @param registry the {@linkplain ResourceKey resource key} that identifies + * the registry. + * @param identifier the {@linkplain NamespacedIdentifier} identifier for the + * ID fixer. + * @param fixer the ID fixer to be registered. + */ + public static void registerFixer(ResourceKey> registry, NamespacedIdentifier identifier, IdFixer fixer) { + SyncedRegistriesImpl.registerFixer(registry, identifier, fixer); + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/WritableRegistry.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/WritableRegistry.java new file mode 100644 index 000000000..310c6f614 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/WritableRegistry.java @@ -0,0 +1,35 @@ +package net.ornithemc.osl.registries.api.registry; + +/** + * A writable registry allows new values to be registered to it. + * + * @param the value type. + * @see Registry + */ +public interface WritableRegistry extends Registry { + + /** + * Registers the given value to the registry. + * + * @param the value type of the value to be registered. + * @param key the resource key that uniquely identifies the value. + * @param value the value to be registered. + * @return the registered value. + */ + V register(ResourceKey key, V value); + + /** + * Registers the given value to the registry. + * + * @param the value type of the value to be registered. + * @param id the ID that uniquely identifies the value. + * @param key the resource key that uniquely identifies the value. + * @param value the value to be registered. + * @return the registered value. + * + * @deprecated use {@link #register(ResourceKey, Object)} instead. + */ + @Deprecated + V register(int id, ResourceKey key, V value); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/BooleanArrayMapper.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/BooleanArrayMapper.java new file mode 100644 index 000000000..0c75768e8 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/BooleanArrayMapper.java @@ -0,0 +1,55 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import java.util.Arrays; + +/** + * An {@linkplain IdMapper} implementation for boolean arrays ({@code boolean[]} + * where IDs are used as indices to the array. The values are moved from the old + * index (the old ID) to the new index (the new ID) within the same array. Since + * {@code boolean} is a primitive type, {@code false} is used as the default or + * "empty" value. + */ +public class BooleanArrayMapper implements IdMapper { + + public static BooleanArrayMapper of(boolean[] registry) { + return new BooleanArrayMapper(registry); + } + + private final boolean[] registry; + private final boolean[] backup; + + private boolean applied; + + private BooleanArrayMapper(boolean[] registry) { + this.registry = registry; + this.backup = new boolean[registry.length]; + } + + @Override + public void apply(RegistryMappings mappings) { + Arrays.fill(this.backup, false); + System.arraycopy(this.registry, 0, this.backup, 0, this.backup.length); + + Arrays.fill(this.registry, false); + + for (int oldId = 0; oldId < this.backup.length; oldId++) { + int newId = mappings.remap(oldId); + + if (newId >= 0) { + this.registry[newId] = this.backup[oldId]; + } + } + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + Arrays.fill(this.registry, false); + System.arraycopy(this.backup, 0, this.registry, 0, this.registry.length); + } + + this.applied = false; + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/DynamicArrays.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/DynamicArrays.java new file mode 100644 index 000000000..9ed4e32d0 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/DynamicArrays.java @@ -0,0 +1,60 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import java.util.Arrays; + +/** + * Utility class for dynamically growing arrays. + */ +public final class DynamicArrays { + + public static int length(T[] array) { + for (int index = array.length - 1; index >= 0; index--) { + if (array[index] != null) { + return index + 1; + } + } + + return 0; + } + + public static T[] set(T[] array, int index, T value) { + array = grow(array, index + 1); + array[index] = value; + + return array; + } + + public static T[] grow(T[] array, int capacity) { + if (capacity > array.length) { + array = Arrays.copyOf(array, newLength(array.length, capacity)); + } + + return array; + } + + public static boolean[] grow(boolean[] array, int capacity) { + if (capacity > array.length) { + array = Arrays.copyOf(array, newLength(array.length, capacity)); + } + + return array; + } + + public static int[] grow(int[] array, int capacity) { + if (capacity > array.length) { + array = Arrays.copyOf(array, newLength(array.length, capacity)); + } + + return array; + } + + // rather than increasing the array length to exactly the requested capacity + // increase it by 50% of the current length to avoid allocating a lot of arrays + private static int newLength(int length, int capacity) { + while (length < capacity) { + length += length / 2; + } + + return length; + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IdFixer.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IdFixer.java new file mode 100644 index 000000000..b6b25ff0a --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IdFixer.java @@ -0,0 +1,24 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +/** + * An ID fixer is used to fix up numerical IDs after registries have been + * remapped. In most cases, a {@linkplain IdMapper ID mapper} is necessary, but + * in some cases, the IDs can be inferred or generated, and an ID mapper is + * either overkill or cannot be used at all. In these cases, an ID fixer is the + * right solution. Some examples of ID fixers are: + *

  • The {@code Id2ObjectBiMap} block state registry. This is + * either automatically filled based on the block registry iteration order, + * or the IDs are generated based on block IDs and metadata values.
  • + *
  • The {@code int id} fields in {@code Block} and {@code Item} in 1.6.4 and + * below. Since the {@code Block[] BY_ID} and {@code Item[] BY_ID} arrays + * are remapped first, the IDs can be inferred from the indices so an ID + * mapper is not needed.
  • + */ +public interface IdFixer { + + /** + * Fix up IDs for the bound registry or map. + */ + void apply(); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IdMapper.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IdMapper.java new file mode 100644 index 000000000..21cbae550 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IdMapper.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +/** + * An ID mapper is used to remap numerical IDs from old to new values and vice + * versa. This could be arrays, lists, or maps that use the IDs as indices or + * keys, or it could be objects that store the IDs in a field. Some examples of + * objects that require an ID mapper are: + *
  • The {@code Block[] BY_ID} field in {@code Block} 1.6.4 and below, which + * uses block IDs as indices to the array.
  • + *
  • The {@code Int2ObjectMap} field in {@code ItemModelShaper} + * which uses item IDs as keys to the map.
  • + *
  • The {@code ItemStat} instances in 1.6.4 and below, which store the item + * ID as a field.
  • + * + *

    + * The Registries API provides several implementations of this interface in this + * package which you can use. + * + * @see BooleanArrayMapper + * @see Int2ObjectMapMapper + * @see IntArrayMapper + * @see IntegerMapMapper + * @see ListMapper + * @see ObjectArrayMapper + */ +public interface IdMapper { + + /** + * Apply the given ID mappings to the bound registry or map. + */ + void apply(RegistryMappings mappings); + + /** + * Undo the given ID mappings and reset the bound registry or map. + */ + void undo(RegistryMappings mappings); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Int2ObjectMapMapper.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Int2ObjectMapMapper.java new file mode 100644 index 000000000..4c6ea8686 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Int2ObjectMapMapper.java @@ -0,0 +1,58 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +/** + * An {@linkplain IdMapper} implementation for fastutil's + * {@linkplain Int2ObjectMap} where IDs are used as keys to the map. The values + * are moved from the old key (the old ID) to the new key (the new ID) within + * the same map. {@code null} is used as the default or "empty" value. + */ +public class Int2ObjectMapMapper implements IdMapper { + + public static Int2ObjectMapMapper of(Int2ObjectMap registry) { + return new Int2ObjectMapMapper(registry); + } + + private final Int2ObjectMap registry; + private final Int2ObjectMap backup; + + private boolean applied; + + @SuppressWarnings("unchecked") + private Int2ObjectMapMapper(Int2ObjectMap registry) { + this.registry = (Int2ObjectMap) registry; + this.backup = new Int2ObjectOpenHashMap<>(registry.size()); + } + + @Override + public void apply(RegistryMappings mappings) { + this.backup.clear(); + this.backup.putAll(this.registry); + + this.registry.clear(); + + for (Int2ObjectMap.Entry e : this.backup.int2ObjectEntrySet()) { + Object value = e.getValue(); + int oldId = e.getIntKey(); + int newId = mappings.remap(oldId); + + if (newId >= 0) { + this.registry.put(newId, value); + } + } + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + this.registry.clear(); + this.registry.putAll(this.backup); + } + + this.applied = false; + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IntArrayMapper.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IntArrayMapper.java new file mode 100644 index 000000000..11274728a --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IntArrayMapper.java @@ -0,0 +1,55 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import java.util.Arrays; + +/** + * An {@linkplain IdMapper} implementation for int arrays ({@code int[]} where + * IDs are used as indices to the array. The values are moved from the old index + * (the old ID) to the new index (the new ID) within the same array. Since + * {@code int} is a primitive type, {@code 0} is used as the default or "empty" + * value. + */ +public class IntArrayMapper implements IdMapper { + + public static IntArrayMapper of(int[] registry) { + return new IntArrayMapper(registry); + } + + private final int[] registry; + private final int[] backup; + + private boolean applied; + + private IntArrayMapper(int[] registry) { + this.registry = registry; + this.backup = new int[registry.length]; + } + + @Override + public void apply(RegistryMappings mappings) { + Arrays.fill(this.backup, 0); + System.arraycopy(this.registry, 0, this.backup, 0, this.backup.length); + + Arrays.fill(this.registry, 0); + + for (int oldId = 0; oldId < this.backup.length; oldId++) { + int newId = mappings.remap(oldId); + + if (newId >= 0) { + this.registry[newId] = this.backup[oldId]; + } + } + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + Arrays.fill(this.registry, 0); + System.arraycopy(this.backup, 0, this.registry, 0, this.registry.length); + } + + this.applied = false; + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IntegerMapMapper.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IntegerMapMapper.java new file mode 100644 index 000000000..5d1235a45 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IntegerMapMapper.java @@ -0,0 +1,58 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import java.util.HashMap; +import java.util.Map; + +/** + * An {@linkplain IdMapper} implementation for maps with {@code Integer} keys + * ({@code Map}) where IDs are used as keys to the map. The values + * are moved from the old key (the old ID) to the new key (the new ID) within + * the same map. {@code null} is used as the default or "empty" value. + */ +public class IntegerMapMapper implements IdMapper { + + public static IntegerMapMapper of(Map registry) { + return new IntegerMapMapper(registry); + } + + private final Map registry; + private final Map backup; + + private boolean applied; + + @SuppressWarnings("unchecked") + private IntegerMapMapper(Map registry) { + this.registry = (Map) registry; + this.backup = new HashMap<>(this.registry.size()); + } + + @Override + public void apply(RegistryMappings mappings) { + this.backup.clear(); + this.backup.putAll(this.registry); + + this.registry.clear(); + + for (Map.Entry e : this.backup.entrySet()) { + Object value = e.getValue(); + int oldId = e.getKey(); + int newId = mappings.remap(oldId); + + if (newId >= 0) { + this.registry.put(newId, value); + } + } + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + this.registry.clear(); + this.registry.putAll(this.backup); + } + + this.applied = false; + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/ListMapper.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/ListMapper.java new file mode 100644 index 000000000..28580c0df --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/ListMapper.java @@ -0,0 +1,64 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import java.util.ArrayList; +import java.util.List; + +/** + * An {@linkplain IdMapper} implementation for lists ({@code List} where IDs + * are used as indices to the list. The values are moved from the old index (the + * old ID) to the new index (the new ID) within the same list. {@code null} is + * used as the default or "empty" value. + */ +public class ListMapper implements IdMapper { + + public static ListMapper of(List registry) { + return new ListMapper(registry); + } + + private final List registry; + private final List backup; + + private boolean applied; + + @SuppressWarnings("unchecked") + private ListMapper(List registry) { + this.registry = (List) registry; + this.backup = new ArrayList<>(registry.size()); + } + + @Override + public void apply(RegistryMappings mappings) { + this.backup.clear(); + this.backup.addAll(this.registry); + + this.registry.clear(); + + for (int oldId = 0; oldId < this.backup.size(); oldId++) { + Object value = this.backup.get(oldId); + + if (value != null) { + int newId = mappings.remap(oldId); + + if (newId >= 0) { + while (newId >= this.registry.size()) { + this.registry.add(null); + } + + this.registry.set(newId, value); + } + } + } + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + this.registry.clear(); + this.registry.addAll(this.backup); + } + + this.applied = false; + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/ObjectArrayMapper.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/ObjectArrayMapper.java new file mode 100644 index 000000000..8d3d7332f --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/ObjectArrayMapper.java @@ -0,0 +1,58 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import java.util.Arrays; + +/** + * An {@linkplain IdMapper} implementation for object arrays ({@code T[]} where + * IDs are used as indices to the array. The values are moved from the old index + * (the old ID) to the new index (the new ID) within the same array. + * {@code null} is used as the default or "empty" value. + */ +public class ObjectArrayMapper implements IdMapper { + + public static ObjectArrayMapper of(T[] registry) { + return new ObjectArrayMapper(registry); + } + + private final Object[] registry; + private final Object[] backup; + + private boolean applied; + + private ObjectArrayMapper(T[] registry) { + this.registry = (Object[]) registry; + this.backup = new Object[registry.length]; + } + + @Override + public void apply(RegistryMappings mappings) { + Arrays.fill(this.backup, null); + System.arraycopy(this.registry, 0, this.backup, 0, this.backup.length); + + Arrays.fill(this.registry, null); + + for (int oldId = 0; oldId < this.backup.length; oldId++) { + Object value = this.backup[oldId]; + + if (value != null) { + int newId = mappings.remap(oldId); + + if (newId >= 0) { + this.registry[newId] = value; + } + } + } + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + Arrays.fill(this.registry, null); + System.arraycopy(this.backup, 0, this.registry, 0, this.registry.length); + } + + this.applied = false; + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/RegistryMappings.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/RegistryMappings.java new file mode 100644 index 000000000..4659068c9 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/RegistryMappings.java @@ -0,0 +1,30 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +/** + * These mappings can be used to map old IDs to new IDs and vice versa. + */ +public interface RegistryMappings { + + /** + * @return the new ID for the given resource key. + */ + int remap(ResourceKey key); + + /** + * @return the new ID for the given resource ID. + */ + int remap(int id); + + /** + * @return the old ID for the given resource key. + */ + int unmap(ResourceKey key); + + /** + * @return the old ID for the given resource ID. + */ + int unmap(int id); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/Constants.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/Constants.java new file mode 100644 index 000000000..909bc52f8 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/Constants.java @@ -0,0 +1,16 @@ +package net.ornithemc.osl.registries.impl; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.networking.api.ChannelIdentifiers; +import net.ornithemc.osl.networking.api.ChannelRegistry; + +public final class Constants { + + public static final int REGISTRY_MAPPINGS_FORMAT = 1; + public static final String REGISTRY_MAPPINGS_FILE_NAME = "registry_mappings.dat"; + public static final String FORMAT_NBT_KEY = "format"; + public static final String REGISTRIES_NBT_KEY = "registries"; + + public static final NamespacedIdentifier OSL_REGISTRY_SYNC_CHANNEL = ChannelRegistry.register(ChannelIdentifiers.from("osl", "registries")); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ClearableRegistry.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ClearableRegistry.java new file mode 100644 index 000000000..a30549293 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ClearableRegistry.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.ornithemc.osl.registries.api.registry.WritableRegistry; + +public interface ClearableRegistry extends WritableRegistry { + + void clear(); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/DefaultedSimpleRegistry.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/DefaultedSimpleRegistry.java new file mode 100644 index 000000000..5f739cf13 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/DefaultedSimpleRegistry.java @@ -0,0 +1,85 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public class DefaultedSimpleRegistry extends SimpleRegistry implements DefaultedRegistry { + + private final NamespacedIdentifier defaultIdentifier; + + private T defaultValue; + + public DefaultedSimpleRegistry(NamespacedIdentifier identifier, NamespacedIdentifier defaultIdentifier) { + super(identifier); + + this.defaultIdentifier = defaultIdentifier; + } + + @Override + public NamespacedIdentifier getDefaultIdentifier() { + return this.defaultIdentifier; + } + + @Override + public V register(int id, ResourceKey key, V value) { + if (this.defaultIdentifier.equals(key.identifier())) { + this.defaultValue = value; + } + + return super.register(id, key, value); + } + + @Override + public T get(int id) { + T value = super.get(id); + return value == null ? this.defaultValue : value; + } + + @Override + public T get(ResourceKey key) { + T value = super.get(key); + return value == null ? this.defaultValue : value; + } + + @Override + public T get(NamespacedIdentifier identifier) { + T value = super.get(identifier); + return value == null ? this.defaultValue : value; + } + + @Override + public int getId(T value) { + int id = super.getId(value); + return id == -1 ? super.getId(this.defaultValue) : id; + } + + @Override + public ResourceKey getKey(T value) { + ResourceKey key = super.getKey(value); + return key == null ? super.getKey(this.defaultValue) : key; + } + + @Override + public NamespacedIdentifier getIdentifier(T value) { + NamespacedIdentifier identifier = super.getIdentifier(value); + return identifier == null ? this.defaultIdentifier : identifier; + } + + @Override + public Registry freeze() { + if (this.defaultValue == null) { + throw new IllegalStateException("Attempted to freeze defaulted registry " + this.identifier() + " before default value was registered!"); + } + + return super.freeze(); + } + + @Override + public void clear() { + super.clear(); + + this.defaultValue = null; + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/RegistriesImpl.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/RegistriesImpl.java new file mode 100644 index 000000000..2b8231958 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/RegistriesImpl.java @@ -0,0 +1,125 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.RegistryEvents; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.ResourceKeys; +import net.ornithemc.osl.registries.api.registry.WritableRegistry; + +public final class RegistriesImpl { + + public static final Logger LOGGER = LogManager.getLogger("OSL|Registries"); + + private static final WritableRegistry> WRITABLE_REGISTRY = new SimpleRegistry<>(NamespacedIdentifiers.from("root")); + private static final Map BOOTSTRAPS = new LinkedHashMap<>(); + + public static final Registry> REGISTRY = WRITABLE_REGISTRY; + + public static WritableRegistry get(ResourceKey> key) { + @SuppressWarnings("unchecked") + ResourceKey> registryKey = (ResourceKey>) (Object) key; + @SuppressWarnings("unchecked") + WritableRegistry registry = (WritableRegistry) WRITABLE_REGISTRY.get(registryKey); + + return registry; + } + + public static SimpleRegistry registerSimple(ResourceKey> key, Registry.Bootstrap bootstrap) { + return register(key, new SimpleRegistry<>(key.identifier()), bootstrap); + } + + public static DefaultedSimpleRegistry registerDefaulted(ResourceKey> key, NamespacedIdentifier defaultIdentifier, Registry.Bootstrap bootstrap) { + return register(key, new DefaultedSimpleRegistry<>(key.identifier(), defaultIdentifier), bootstrap); + } + + public static > R register(ResourceKey> key, R registry, Registry.Bootstrap bootstrap) { + if (!NamespacedIdentifiers.equals(key.identifier(), registry.identifier())) { + throw new IllegalArgumentException("illegal key " + key + " for registry " + registry.identifier()); + } + + @SuppressWarnings("unchecked") + ResourceKey> registryKey = (ResourceKey>) (Object) key; + NamespacedIdentifier identifier = registryKey.identifier(); + + WRITABLE_REGISTRY.register(registryKey, registry); + BOOTSTRAPS.put(identifier, bootstrap); + + if (registry != null) { + LOGGER.debug("Added {} {}", registry.getClass().getSimpleName(), key.identifier()); + } + + return registry; + } + + public static V registerMapping(Registry registry, ResourceKey key, V value) { + return ((WritableRegistry) registry).register(key, value); + } + + public static V registerMapping(Registry registry, NamespacedIdentifier identifier, V value) { + return registerMapping(registry, ResourceKeys.from(registry.identifier(), identifier), value); + } + + @Deprecated + public static V registerMapping(Registry registry, int id, ResourceKey key, V value) { + value = ((WritableRegistry) registry).register(id, key, value); + + if (value != null) { + LOGGER.debug("[{}] registered {} {}", id, key.identifier()); + } + + return value; + } + + @Deprecated + public static V registerMapping(Registry registry, int id, NamespacedIdentifier identifier, V value) { + return registerMapping(registry, id, ResourceKeys.from(registry.identifier(), identifier), value); + } + + public static void init() { + RegistryEvents.BOOTSTRAP_REGISTRIES.invoker().run(); + + bootstrap(); + freeze(); + validate(); + + LOGGER.info("Bootstrapped {} registries.", BOOTSTRAPS.size()); + } + + private static void bootstrap() { + BOOTSTRAPS.forEach((identifier, bootstrap) -> { + try { + bootstrap.init(); + } catch (Exception e) { + throw new IllegalStateException("error while bootstrapping registry " + identifier, e); + } + }); + } + + private static void freeze() { + WRITABLE_REGISTRY.freeze(); + + for (Registry registry : WRITABLE_REGISTRY) { + registry.freeze(); + } + } + + private static void validate() { + if (REGISTRY.keySet().isEmpty()) { + throw new IllegalStateException("Unable to load registries!"); + } + + for (Registry registry : REGISTRY) { + if (registry.keySet().isEmpty()) { + throw new IllegalStateException("Registry " + registry.identifier() + " is empty after bootstrap!"); + } + } + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ResourceKeyImpl.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ResourceKeyImpl.java new file mode 100644 index 000000000..dcb933b88 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ResourceKeyImpl.java @@ -0,0 +1,30 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public final class ResourceKeyImpl implements ResourceKey { + + private final NamespacedIdentifier registry; + private final NamespacedIdentifier identifier; + + ResourceKeyImpl(NamespacedIdentifier registry, NamespacedIdentifier identifier) { + this.registry = registry; + this.identifier = identifier; + } + + @Override + public String toString() { + return "ResourceKey[" + this.registry + "/" + this.identifier + "]"; + } + + @Override + public NamespacedIdentifier registry() { + return this.registry; + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ResourceKeysImpl.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ResourceKeysImpl.java new file mode 100644 index 000000000..f00a2c192 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ResourceKeysImpl.java @@ -0,0 +1,42 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; + +public final class ResourceKeysImpl { + + private static final Map> RESOURCE_KEYS = new HashMap<>(); + + public static ResourceKeyImpl from(NamespacedIdentifier identifier) { + return from(RegistriesImpl.REGISTRY.identifier(), identifier); + } + + @SuppressWarnings("unchecked") + public static ResourceKeyImpl from(NamespacedIdentifier registry, NamespacedIdentifier identifier) { + return (ResourceKeyImpl) RESOURCE_KEYS.computeIfAbsent(new Key(registry, identifier), key -> new ResourceKeyImpl<>(registry, identifier)); + } + + private static final class Key { + + private final NamespacedIdentifier registry; + private final NamespacedIdentifier identifier; + + private Key(NamespacedIdentifier registry, NamespacedIdentifier identifier) { + this.registry = registry; + this.identifier = identifier; + } + + @Override + public boolean equals(Object o) { + return this.registry.equals(((Key) o).registry) && this.identifier.equals(((Key) o).identifier); + } + + @Override + public int hashCode() { + return Objects.hash(this.registry, this.identifier); + } + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SimpleRegistry.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SimpleRegistry.java new file mode 100644 index 000000000..077dc403e --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SimpleRegistry.java @@ -0,0 +1,149 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; +import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; +import it.unimi.dsi.fastutil.objects.Reference2IntMap; +import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.WritableRegistry; + +public class SimpleRegistry implements WritableRegistry, ClearableRegistry { + + private final NamespacedIdentifier identifier; + + private final Int2ReferenceMap values; + private final Reference2IntMap ids; + private final Map registry; + private final Map> keys; + private final Map identifiers; + + private int nextId = 0; + private boolean frozen; + + public SimpleRegistry(NamespacedIdentifier identifier) { + this.identifier = identifier; + + this.values = new Int2ReferenceOpenHashMap<>(); + this.ids = new Reference2IntOpenHashMap<>(); + this.registry = new HashMap<>(); + this.keys = new IdentityHashMap<>(); + this.identifiers = new IdentityHashMap<>(); + + this.ids.defaultReturnValue(-1); + } + + @Override + public V register(ResourceKey key, V value) { + return this.register(this.nextId++, key, value); + } + + @Override + public V register(int id, ResourceKey key, V value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + if (id < 0) { + throw new IllegalStateException("invalid ID " + id + " (must be >= 0)"); + } + if (this.values.containsKey(id)) { + throw new IllegalStateException("duplicate ID " + id + " (" + this.getIdentifier(this.get(id)) + " and " + key.identifier() + ")"); + } + if (this.registry.containsKey(key.identifier())) { + throw new IllegalStateException("duplicate Namespaced ID " + key.identifier() + " (" + this.getId(this.get(key)) + " and " + id + ")"); + } + if (this.ids.containsKey(value) || this.keys.containsKey(value) || this.identifiers.containsKey(value)) { + throw new IllegalStateException("value registered twice (" + this.getId(value) + ", " + this.getIdentifier(value) + " and " + id + ", " + key.identifier() + ")"); + } + + this.values.put(id, value); + this.ids.put(value, id); + this.registry.put(key.identifier(), value); + this.keys.put(value, key); + this.identifiers.put(value, key.identifier()); + + this.nextId = Math.max(this.nextId, id + 1); + + return value; + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } + + @Override + public T get(int id) { + return this.values.get(id); + } + + @Override + public T get(ResourceKey key) { + return this.registry.get(key.identifier()); + } + + @Override + public T get(NamespacedIdentifier identifier) { + return this.registry.get(identifier); + } + + @Override + public int getId(T value) { + return this.ids.getInt(value); + } + + @Override + public ResourceKey getKey(T value) { + return this.keys.get(value); + } + + @Override + public NamespacedIdentifier getIdentifier(T value) { + return this.identifiers.get(value); + } + + @Override + public Set> keySet() { + return this.keys.values().stream().collect(Collectors.toSet()); + } + + @Override + public Set identifierSet() { + return this.registry.keySet(); + } + + @Override + public Iterator iterator() { + return this.registry.values().iterator(); + } + + @Override + public Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public void clear() { + this.values.clear(); + this.ids.clear(); + this.registry.clear(); + this.keys.clear(); + this.identifiers.clear(); + + this.nextId = 0; + this.frozen = false; + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java new file mode 100644 index 000000000..4c006c8df --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java @@ -0,0 +1,101 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registries; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.sync.IdFixer; +import net.ornithemc.osl.registries.api.registry.sync.IdMapper; +import net.ornithemc.osl.registries.api.registry.sync.RegistryMappings; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMapper; + +public final class SyncedRegistriesImpl { + + public static final Registry SYNCED_REGISTRIES = new SimpleRegistry<>(NamespacedIdentifiers.from("synced_registry")); + + public static void register(ResourceKey> registry) { + NamespacedIdentifier identifier = registry.identifier(); + Registry instance = Registries.get(registry); + + if (instance == null) { + throw new IllegalArgumentException("unknown registry " + identifier); + } else if (!(instance instanceof ClearableRegistry)) { + throw new IllegalArgumentException("unsyncable registry " + identifier); + } else { + SyncedRegistry synced = SYNCED_REGISTRIES.get(identifier); + + if (synced != null) { + throw new IllegalArgumentException("duplicate synced registry " + identifier); + } else { + Registry.register(SYNCED_REGISTRIES, registry.identifier(), synced = new SyncedRegistry(instance)); + } + + synced.registerMapper(identifier, RegistryMapper.of(instance)); + } + } + + public static void registerMapper(ResourceKey> registry, NamespacedIdentifier identifier, IdMapper mapper) { + SyncedRegistry synced = SYNCED_REGISTRIES.get(registry.identifier()); + + if (synced == null) { + throw new IllegalArgumentException("registry " + registry.identifier() + " is not synced!"); + } else { + synced.registerMapper(identifier, mapper); + } + } + + public static void registerFixer(ResourceKey> registry, NamespacedIdentifier identifier, IdFixer fixer) { + SyncedRegistry synced = SYNCED_REGISTRIES.get(registry.identifier()); + + if (synced == null) { + throw new IllegalArgumentException("registry " + registry.identifier() + " is not synced!"); + } else { + synced.registerFixer(identifier, fixer); + } + } + + public static void init() { + for (Registry registry : Registries.REGISTRY) { + SyncedRegistry synced = SYNCED_REGISTRIES.get(registry.identifier()); + + if (synced != null) { + synced.init(); + } else { + RegistriesImpl.LOGGER.debug("registry {} is not synced!", registry.identifier()); + } + } + } + + public static void resetMappings() { + for (SyncedRegistry registry : SYNCED_REGISTRIES) { + registry.getMappings().reset(); + } + } + + public static void applyMappings() { + for (SyncedRegistry registry : SYNCED_REGISTRIES) { + RegistryMappings mappings = registry.getMappings(); + + for (IdMapper mapper : registry.getMappers()) { + mapper.apply(mappings); + } + for (IdFixer fixer : registry.getFixers()) { + fixer.apply(); + } + } + } + + public static void undoMappings() { + for (SyncedRegistry registry : SYNCED_REGISTRIES) { + RegistryMappings mappings = registry.getMappings(); + + for (IdMapper mapper : registry.getMappers()) { + mapper.undo(mappings); + } + for (IdFixer fixer : registry.getFixers()) { + fixer.apply(); + } + } + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistry.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistry.java new file mode 100644 index 000000000..6bfad4dad --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistry.java @@ -0,0 +1,72 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.sync.IdFixer; +import net.ornithemc.osl.registries.api.registry.sync.IdMapper; +import net.ornithemc.osl.registries.impl.registry.sync.SerializableRegistryMappings; + +public class SyncedRegistry { + + private final Registry registry; + + private final SerializableRegistryMappings mappings; + private final Map mappers; + private final Map fixers; + + public SyncedRegistry(Registry registry) { + this.registry = registry; + + this.mappings = SerializableRegistryMappings.of(this.registry); + this.mappers = new LinkedHashMap<>(); + this.fixers = new LinkedHashMap<>(); + } + + public void registerMapper(NamespacedIdentifier identifier, IdMapper mapper) { + if (this.mappers.containsKey(identifier)) { + throw new IllegalArgumentException("duplicate ID mapper " + identifier + " for registry " + this.registry.identifier()); + } else { + this.mappers.put(identifier, mapper); + + if (mapper != null) { + RegistriesImpl.LOGGER.debug("[{}] added ID mapper {}", this.registry.identifier(), identifier); + } + } + } + + public void registerFixer(NamespacedIdentifier identifier, IdFixer fixer) { + if (this.fixers.containsKey(identifier)) { + throw new IllegalArgumentException("duplicate ID fixer " + identifier + " for registry " + this.registry.identifier()); + } else { + this.fixers.put(identifier, fixer); + + if (fixer != null) { + RegistriesImpl.LOGGER.debug("[{}] added ID fixer {}", this.registry.identifier(), identifier); + } + } + } + + public void init() { + this.mappings.reset(); + } + + public NamespacedIdentifier identifier() { + return this.registry.identifier(); + } + + public SerializableRegistryMappings getMappings() { + return this.mappings; + } + + public Collection getMappers() { + return this.mappers.values(); + } + + public Collection getFixers() { + return this.fixers.values(); + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMapper.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMapper.java new file mode 100644 index 000000000..d3aef7ebc --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMapper.java @@ -0,0 +1,81 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.WritableRegistry; +import net.ornithemc.osl.registries.api.registry.sync.IdMapper; +import net.ornithemc.osl.registries.api.registry.sync.RegistryMappings; +import net.ornithemc.osl.registries.impl.registry.ClearableRegistry; +import net.ornithemc.osl.registries.impl.registry.SimpleRegistry; + +public class RegistryMapper implements IdMapper { + + public static RegistryMapper of(Registry registry) { + if (registry instanceof ClearableRegistry) { + return new RegistryMapper(registry); + } else { + throw new IllegalArgumentException("cannot create mapper for non-clearable registry " + registry.identifier()); + } + } + + private final ClearableRegistry registry; + private final ClearableRegistry backup; + + private boolean applied; + + @SuppressWarnings("unchecked") + private RegistryMapper(Registry registry) { + this.registry = (ClearableRegistry) registry; + this.backup = new SimpleRegistry<>(registry.identifier()); + } + + @Override + public void apply(RegistryMappings mappings) { + this.backup.clear(); + + for (Object value : this.registry) { + ResourceKey key = this.registry.getKey(value); + int id = this.registry.getId(value); + + register(this.backup, id, key, value); + } + + this.registry.clear(); + + for (Object value : this.backup) { + ResourceKey key = this.backup.getKey(value); + int id = mappings.remap(key); + + if (id >= 0) { + register(this.registry, id, key, value); + } + } + + this.registry.freeze(); + + this.applied = true; + } + + @Override + public void undo(RegistryMappings mappings) { + if (this.applied) { + this.registry.clear(); + + for (Object value : this.backup) { + int id = this.backup.getId(value); + ResourceKey key = this.backup.getKey(value); + + register(this.registry, id, key, value); + } + + this.registry.freeze(); + } + + this.applied = false; + } + + @SuppressWarnings("deprecation") + private static void register(WritableRegistry registry, int id, ResourceKey key, Object value) { + registry.register(id, key, value); + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMappingException.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMappingException.java new file mode 100644 index 000000000..92252a748 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMappingException.java @@ -0,0 +1,13 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +@SuppressWarnings("serial") +public class RegistryMappingException extends Exception { + + public RegistryMappingException(String message) { + super(message); + } + + public RegistryMappingException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMappingSource.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMappingSource.java new file mode 100644 index 000000000..768484742 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMappingSource.java @@ -0,0 +1,7 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +public enum RegistryMappingSource { + + WORLD_SAVE, REMOTE_SERVER, CLIENT + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java new file mode 100644 index 000000000..66d5a57ab --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java @@ -0,0 +1,155 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.ints.Int2IntMap; +import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.sync.RegistryMappings; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +public class SerializableRegistryMappings implements RegistryMappings { + + public static SerializableRegistryMappings of(Registry registry) { + return new SerializableRegistryMappings(registry); + } + + private final Registry registry; + + private final Object2IntMap mappings = new Object2IntOpenHashMap<>(); + private final Object2IntMap unmappings = new Object2IntOpenHashMap<>(); + + private final Int2IntMap idMappings = new Int2IntOpenHashMap(); + private final Int2IntMap idUnmappings = new Int2IntOpenHashMap(); + + @SuppressWarnings("unchecked") + private SerializableRegistryMappings(Registry registry) { + this.registry = (Registry) registry; + } + + @Override + public int remap(ResourceKey key) { + return this.mappings.getOrDefault(key.identifier(), -1); + } + + @Override + public int remap(int id) { + return this.idMappings.getOrDefault(id, -1); + } + + @Override + public int unmap(ResourceKey key) { + return this.unmappings.getOrDefault(key.identifier(), -1); + } + + @Override + public int unmap(int id) { + return this.idUnmappings.getOrDefault(id, -1); + } + + public void read(M medium, Deserializer deserializer, RegistryMappingSource source) throws IOException, RegistryMappingException { + this.init(); + deserializer.deserialize(medium, this.mappings, source); + this.build(source); + } + + public void write(M medium, Serializer serializer) throws IOException { + serializer.serialize(medium, this.mappings); + } + + private void clear() { + this.mappings.clear(); + this.unmappings.clear(); + + this.idMappings.clear(); + this.idUnmappings.clear(); + } + + public void reset() { + this.clear(); + + for (Object value : this.registry) { + NamespacedIdentifier identifier = this.registry.getIdentifier(value); + int id = this.registry.getId(value); + + this.mappings.put(identifier, id); + this.unmappings.put(identifier, id); + + this.idMappings.put(id, id); + this.idUnmappings.put(id, id); + } + } + + private void init() { + this.clear(); + + for (Object value : this.registry) { + NamespacedIdentifier identifier = this.registry.getIdentifier(value); + int id = this.registry.getId(value); + + this.unmappings.put(identifier, id); + } + } + + private void build(RegistryMappingSource source) throws RegistryMappingException { + // the saved mappings may be incomplete for the current mod set + // but no entries should be dropped, so assign a new id + if (source == RegistryMappingSource.WORLD_SAVE) { + int nextId = this.mappings.values().intStream().max().getAsInt() + 1; + + for (NamespacedIdentifier identifier : this.unmappings.keySet()) { + if (!this.mappings.containsKey(identifier)) { + this.mappings.put(identifier, nextId++); + } + } + } + + this.idMappings.clear(); + this.idUnmappings.clear(); + + for (NamespacedIdentifier identifier : this.mappings.keySet()) { + int newId = this.mappings.getInt(identifier); + int oldId = this.unmappings.getInt(identifier); + + if (oldId >= 0) { + this.idMappings.put(oldId, newId); + } else if (source == RegistryMappingSource.REMOTE_SERVER) { + throw new RegistryMappingException("[" + this.registry.identifier() + "] received mapping for unknown entry " + identifier); + } else { + RegistriesImpl.LOGGER.warn("[{}] received mapping for unknown entry {}", this.registry.identifier(), identifier); + } + } + + for (NamespacedIdentifier identifier : this.unmappings.keySet()) { + int oldId = this.unmappings.getInt(identifier); + int newId = this.mappings.getInt(identifier); + + if (newId >= 0) { + this.idUnmappings.put(newId, oldId); + } else if (source == RegistryMappingSource.CLIENT) { + throw new RegistryMappingException("[" + this.registry.identifier() + "] missing mapping for required entry " + identifier); + } else { + RegistriesImpl.LOGGER.warn("[{}] missing mapping for required entry {}", this.registry.identifier(), identifier); + } + } + } + + @FunctionalInterface + public interface Serializer { + + void serialize(M medium, Object2IntMap mappings) throws IOException; + + } + + @FunctionalInterface + public interface Deserializer { + + void deserialize(M Medium, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException; + + } +} diff --git a/settings.gradle b/settings.gradle index a6007e878..e53df0695 100644 --- a/settings.gradle +++ b/settings.gradle @@ -25,7 +25,8 @@ include ':libraries:core:core-mc14w27a-mc1.14.4' include ':libraries:blocks' include ':libraries:blocks:blocks-mca1.0.1_01-mc1.6.4' include ':libraries:blocks:blocks-mc13w36a-mc14w26c' -include ':libraries:blocks:blocks-mc14w27a-mc17w46a' +include ':libraries:blocks:blocks-mc14w27a-mc15w35a' +include ':libraries:blocks:blocks-mc15w36a-mc17w46a' include ':libraries:blocks:blocks-mc17w47a-mc18w31a' include ':libraries:blocks:blocks-mc18w32a-mc1.13.2' include ':libraries:blocks:blocks-mc18w43a-mc1.14.4' @@ -116,6 +117,16 @@ include ':libraries:networking-impl:networking-impl-mc1.13-pre3-mc1.13-pre3' include ':libraries:networking-impl:networking-impl-mc1.13-pre4-mc1.13.2' include ':libraries:networking-impl:networking-impl-mc18w43a-mc1.14.4' +include ':libraries:registries' +include ':libraries:registries:registries-mca1.0.1_01-mc12w17a' +include ':libraries:registries:registries-mc12w18a-mc1.6.4' +include ':libraries:registries:registries-mc13w36a-mc14w26c' +include ':libraries:registries:registries-mc14w27a-mc17w46a' +include ':libraries:registries:registries-mc17w47a-mc18w31a' +include ':libraries:registries:registries-mc18w32a-mc1.13.2' +include ':libraries:registries:registries-mc18w43a-mc19w03c' +include ':libraries:registries:registries-mc19w04a-mc1.14.4' + include ':libraries:resource-loader' include ':libraries:resource-loader:resource-loader-mca1.0.1_01-mca1.2.1_01' include ':libraries:resource-loader:resource-loader-mca1.2.2-mc1.2.5'