├── .gitattributes ├── src ├── shim │ └── java │ │ └── net │ │ └── optifine │ │ └── CustomColors.java ├── debug │ ├── resources │ │ ├── assets │ │ │ └── testmod │ │ │ │ ├── models │ │ │ │ ├── item │ │ │ │ │ ├── white_block.json │ │ │ │ │ └── translucent_white_block.json │ │ │ │ └── block │ │ │ │ │ ├── white_fluid.json │ │ │ │ │ ├── white_block.json │ │ │ │ │ └── translucent_white_block.json │ │ │ │ ├── blockstates │ │ │ │ ├── white_block.json │ │ │ │ ├── white_fluid.json │ │ │ │ └── translucent_white_block.json │ │ │ │ ├── textures │ │ │ │ └── block │ │ │ │ │ ├── white_block.png │ │ │ │ │ ├── white_fluid_flow.png │ │ │ │ │ ├── white_fluid_still.png │ │ │ │ │ └── translucent_white_block.png │ │ │ │ └── lang │ │ │ │ └── en_us.json │ │ ├── pack.mcmeta │ │ ├── data │ │ │ └── minecraft │ │ │ │ └── tags │ │ │ │ └── fluids │ │ │ │ └── water.json │ │ └── riftmod.json │ └── java │ │ └── org │ │ └── dimdev │ │ └── testmod │ │ ├── CPacketTest.java │ │ ├── ItemPacketTester.java │ │ ├── TestMessage.java │ │ ├── ExplosionCommand.java │ │ ├── TestDimension.java │ │ ├── ChangeDimensionCommand.java │ │ ├── WhiteFluid.java │ │ └── TestMod.java └── main │ ├── java │ ├── org │ │ └── dimdev │ │ │ ├── rift │ │ │ ├── listener │ │ │ │ ├── BlockAdder.java │ │ │ │ ├── FluidAdder.java │ │ │ │ ├── ItemAdder.java │ │ │ │ ├── SoundAdder.java │ │ │ │ ├── EntityTypeAdder.java │ │ │ │ ├── MobEffectAdder.java │ │ │ │ ├── EnchantmentAdder.java │ │ │ │ ├── ParticleTypeAdder.java │ │ │ │ ├── BootstrapListener.java │ │ │ │ ├── client │ │ │ │ │ ├── KeybindHandler.java │ │ │ │ │ ├── OverlayRenderer.java │ │ │ │ │ ├── ClientTickable.java │ │ │ │ │ ├── KeyBindingAdder.java │ │ │ │ │ ├── TextureAdder.java │ │ │ │ │ ├── TileEntityRendererAdder.java │ │ │ │ │ ├── EntityRendererAdder.java │ │ │ │ │ ├── GameGuiAdder.java │ │ │ │ │ └── AmbientMusicTypeProvider.java │ │ │ │ ├── MinecraftStartListener.java │ │ │ │ ├── TileEntityTypeAdder.java │ │ │ │ ├── DispenserBehaviorAdder.java │ │ │ │ ├── ServerTickable.java │ │ │ │ ├── WorldChanger.java │ │ │ │ ├── BurnTimeProvider.java │ │ │ │ ├── ChunkEventListener.java │ │ │ │ ├── DataPackFinderAdder.java │ │ │ │ ├── ResourcePackFinderAdder.java │ │ │ │ ├── BiomeAdder.java │ │ │ │ ├── MessageAdder.java │ │ │ │ ├── CommandAdder.java │ │ │ │ ├── ToolEfficiencyProvider.java │ │ │ │ ├── RecipeAdder.java │ │ │ │ ├── RecipeSerializerAdder.java │ │ │ │ ├── ArgumentTypeAdder.java │ │ │ │ ├── StructureAdder.java │ │ │ │ ├── DimensionTypeAdder.java │ │ │ │ ├── PacketAdder.java │ │ │ │ └── ChunkGeneratorReplacer.java │ │ │ ├── network │ │ │ │ ├── MessageContext.java │ │ │ │ ├── MessageRegistrator.java │ │ │ │ ├── ServerMessageContext.java │ │ │ │ ├── ClientMessageContext.java │ │ │ │ └── Message.java │ │ │ ├── injectedmethods │ │ │ │ ├── RiftCPacketCustomPayload.java │ │ │ │ └── RiftFluid.java │ │ │ ├── mixin │ │ │ │ ├── core │ │ │ │ │ ├── MixinMinecraftServer.java │ │ │ │ │ ├── client │ │ │ │ │ │ ├── MixinClientBrandRetriever.java │ │ │ │ │ │ ├── MixinItemRenderer.java │ │ │ │ │ │ ├── MixinLavaFluid.java │ │ │ │ │ │ ├── MixinWaterFluid.java │ │ │ │ │ │ └── MixinLayerArmorBase.java │ │ │ │ │ └── MixinVanillaPack.java │ │ │ │ ├── hook │ │ │ │ │ ├── MixinStructureIO.java │ │ │ │ │ ├── MixinDimensionType.java │ │ │ │ │ ├── MixinRecipeSerializers.java │ │ │ │ │ ├── MixinItem.java │ │ │ │ │ ├── MixinSoundEvent.java │ │ │ │ │ ├── MixinFeature.java │ │ │ │ │ ├── MixinPotion.java │ │ │ │ │ ├── MixinCPacketCustomPayload.java │ │ │ │ │ ├── client │ │ │ │ │ │ ├── MixinGuiIngame.java │ │ │ │ │ │ ├── MixinModelBakery.java │ │ │ │ │ │ ├── MixinGameSettings.java │ │ │ │ │ │ ├── MixinRenderManager.java │ │ │ │ │ │ ├── MixinTileEntityRendererDispatcher.java │ │ │ │ │ │ ├── MixinEntityPlayerSP.java │ │ │ │ │ │ ├── MixinMinecraft.java │ │ │ │ │ │ └── MixinNetHandlerPlayClient.java │ │ │ │ │ ├── MixinEnchantment.java │ │ │ │ │ ├── MixinParticleType.java │ │ │ │ │ ├── MixinArgumentTypes.java │ │ │ │ │ ├── MixinFluid.java │ │ │ │ │ ├── MixinFurnace.java │ │ │ │ │ ├── MixinBlock.java │ │ │ │ │ ├── MixinChunk.java │ │ │ │ │ ├── MixinCommands.java │ │ │ │ │ ├── MixinRecipeManager.java │ │ │ │ │ ├── MixinBiome.java │ │ │ │ │ ├── MixinOverworldBiomeProvider.java │ │ │ │ │ ├── MixinItemTool.java │ │ │ │ │ ├── MixinAnvilSaveHandler.java │ │ │ │ │ ├── MixinWorldServer.java │ │ │ │ │ ├── MixinBootstrap.java │ │ │ │ │ ├── MixinNetHandlerPlayServer.java │ │ │ │ │ ├── MixinEntityType.java │ │ │ │ │ ├── MixinTileEntityType.java │ │ │ │ │ ├── MixinEnumConnectionState.java │ │ │ │ │ └── MixinMinecraftServer.java │ │ │ │ └── optifine │ │ │ │ │ ├── client │ │ │ │ │ ├── MixinCustomColors.java │ │ │ │ │ └── MixinBlockFluidRenderer.java │ │ │ │ │ └── MixinVanillaPack.java │ │ │ ├── util │ │ │ │ ├── RegistryUtil.java │ │ │ │ ├── NBTSerializer.java │ │ │ │ ├── NBTSerializable.java │ │ │ │ ├── ItemTierImpl.java │ │ │ │ └── ArmorMaterialImpl.java │ │ │ ├── LateRift.java │ │ │ ├── resources │ │ │ │ ├── ResourceManager.java │ │ │ │ ├── ModPackFinder.java │ │ │ │ └── ModPack.java │ │ │ └── Rift.java │ │ │ ├── riftloader │ │ │ ├── listener │ │ │ │ ├── InitializationListener.java │ │ │ │ └── Instantiator.java │ │ │ ├── Side.java │ │ │ ├── RiftAccessTransformer.java │ │ │ ├── launch │ │ │ │ ├── RiftLoaderServerTweaker.java │ │ │ │ ├── RiftLoaderClientTweaker.java │ │ │ │ └── RiftLoaderTweaker.java │ │ │ ├── DuplicateModException.java │ │ │ ├── ModInfo.java │ │ │ ├── OptifineLoader.java │ │ │ ├── OptifineDevTransformer.java │ │ │ └── Main.java │ │ │ ├── utils │ │ │ ├── InstanceListMap.java │ │ │ ├── InstanceMap.java │ │ │ ├── NBTConstants.java │ │ │ └── ReflectionUtils.java │ │ │ └── accesstransform │ │ │ ├── AccessLevel.java │ │ │ ├── AccessTransformationSet.java │ │ │ ├── ElementReference.java │ │ │ └── AccessTransformer.java │ └── com │ │ └── chocohead │ │ └── rift │ │ ├── ClassMapping.java │ │ ├── MappingBlob.java │ │ └── RemappingClassAdapter.java │ └── resources │ ├── mixins.rift.no_optifine.json │ ├── mixins.rift.optifine.json │ ├── riftmod.json │ ├── mixins.rift.core.json │ ├── profile.json │ ├── mixins.rift.hooks.json │ └── access_transformations.at ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── optimap.srg ├── .gitignore ├── .travis.yml ├── LICENSE ├── gradlew.bat ├── gradlew └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /src/shim/java/net/optifine/CustomColors.java: -------------------------------------------------------------------------------- 1 | package net.optifine; 2 | 3 | class CustomColors { 4 | 5 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chocohead/Rift/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/debug/resources/assets/testmod/models/item/white_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "testmod:block/white_block" 3 | } 4 | -------------------------------------------------------------------------------- /src/debug/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "pack_format": 4, 4 | "description": "Test Mod" 5 | } 6 | } -------------------------------------------------------------------------------- /src/debug/resources/assets/testmod/models/item/translucent_white_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "testmod:block/translucent_white_block" 3 | } 4 | -------------------------------------------------------------------------------- /src/debug/resources/assets/testmod/blockstates/white_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "": { "model": "testmod:block/white_block" } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/debug/resources/assets/testmod/models/block/white_fluid.json: -------------------------------------------------------------------------------- 1 | { 2 | "textures": { 3 | "particle": "testmod:block/white_fluid_still" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/debug/resources/assets/testmod/blockstates/white_fluid.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "": { "model": "testmod:block/white_fluid" } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/BlockAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | public interface BlockAdder { 4 | void registerBlocks(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/FluidAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | public interface FluidAdder { 4 | void registerFluids(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/ItemAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | public interface ItemAdder { 4 | void registerItems(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/SoundAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | public interface SoundAdder { 4 | void registerSounds(); 5 | } 6 | -------------------------------------------------------------------------------- /src/debug/resources/assets/testmod/blockstates/translucent_white_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "": { "model": "testmod:block/translucent_white_block" } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/debug/resources/assets/testmod/models/block/white_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "block/cube_all", 3 | "textures": { 4 | "all": "testmod:block/white_block" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/debug/resources/assets/testmod/textures/block/white_block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chocohead/Rift/HEAD/src/debug/resources/assets/testmod/textures/block/white_block.png -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/EntityTypeAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | public interface EntityTypeAdder { 4 | void registerEntityTypes(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/MobEffectAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | public interface MobEffectAdder { 4 | void registerMobEffects(); 5 | } 6 | -------------------------------------------------------------------------------- /src/debug/resources/data/minecraft/tags/fluids/water.json: -------------------------------------------------------------------------------- 1 | { 2 | "replace": false, 3 | "values": [ 4 | "testmod:white_fluid", 5 | "testmod:flowing_white_fluid" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/EnchantmentAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | public interface EnchantmentAdder { 4 | void registerEnchantments(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/ParticleTypeAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | public interface ParticleTypeAdder { 4 | void registerParticles(); 5 | } 6 | -------------------------------------------------------------------------------- /src/debug/resources/assets/testmod/textures/block/white_fluid_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chocohead/Rift/HEAD/src/debug/resources/assets/testmod/textures/block/white_fluid_flow.png -------------------------------------------------------------------------------- /src/debug/resources/assets/testmod/textures/block/white_fluid_still.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chocohead/Rift/HEAD/src/debug/resources/assets/testmod/textures/block/white_fluid_still.png -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/BootstrapListener.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | public interface BootstrapListener { 4 | void afterVanillaBootstrap(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/client/KeybindHandler.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener.client; 2 | 3 | public interface KeybindHandler { 4 | void processKeybinds(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/client/OverlayRenderer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener.client; 2 | 3 | public interface OverlayRenderer { 4 | void renderOverlay(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/MinecraftStartListener.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | public interface MinecraftStartListener { 4 | void onMinecraftStart(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/TileEntityTypeAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | public interface TileEntityTypeAdder { 4 | void registerTileEntityTypes(); 5 | } 6 | -------------------------------------------------------------------------------- /src/debug/resources/assets/testmod/models/block/translucent_white_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "block/cube_all", 3 | "textures": { 4 | "all": "testmod:block/translucent_white_block" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/debug/resources/assets/testmod/textures/block/translucent_white_block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chocohead/Rift/HEAD/src/debug/resources/assets/testmod/textures/block/translucent_white_block.png -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/DispenserBehaviorAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | public interface DispenserBehaviorAdder { 4 | void registerDispenserBehaviors(); 5 | } 6 | -------------------------------------------------------------------------------- /src/debug/resources/riftmod.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "testmod", 3 | "name": "TestMod", 4 | "authors": [ 5 | "Runemoro" 6 | ], 7 | "listeners": [ 8 | "org.dimdev.testmod.TestMod" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/ServerTickable.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import net.minecraft.server.MinecraftServer; 4 | 5 | public interface ServerTickable { 6 | void serverTick(MinecraftServer server); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/client/ClientTickable.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener.client; 2 | 3 | import net.minecraft.client.Minecraft; 4 | 5 | public interface ClientTickable { 6 | void clientTick(Minecraft client); 7 | } 8 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip 6 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/WorldChanger.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import net.minecraft.world.biome.Biome; 4 | 5 | public interface WorldChanger { 6 | void modifyBiome(int biomeId, String biomeName, Biome biome); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/BurnTimeProvider.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import net.minecraft.item.Item; 4 | import java.util.Map; 5 | 6 | public interface BurnTimeProvider { 7 | void registerBurnTimes(Map burnTimeMap); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/ChunkEventListener.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import net.minecraft.world.chunk.Chunk; 4 | 5 | public interface ChunkEventListener { 6 | void onChunkLoad(Chunk chunk); 7 | void onChunkUnload(Chunk chunk); 8 | } 9 | -------------------------------------------------------------------------------- /optimap.srg: -------------------------------------------------------------------------------- 1 | MD: net/optifine/CustomColors/getFluidColor (Lnet/minecraft/world/IWorldReader;Lnet/minecraft/block/state/IBlockState;Lnet/minecraft/util/math/BlockPos;Lnet/optifine/render/RenderEnv;)I net/optifine/CustomColors/getFluidColor (Laye;Lblc;Lel;Lnet/optifine/render/RenderEnv;)I 2 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/network/MessageContext.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.network; 2 | 3 | import net.minecraft.network.NetworkManager; 4 | 5 | public interface MessageContext { 6 | NetworkManager getNetworkManager(); 7 | 8 | void reply(Message message); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/DataPackFinderAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import net.minecraft.resources.IPackFinder; 4 | 5 | import java.util.List; 6 | 7 | public interface DataPackFinderAdder { 8 | List getDataPackFinders(); 9 | } 10 | -------------------------------------------------------------------------------- /src/debug/resources/assets/testmod/lang/en_us.json: -------------------------------------------------------------------------------- 1 | { 2 | "block.testmod.white_block": "White Block", 3 | "block.testmod.translucent_white_block": "Translucent White Block", 4 | "item.testmod.white_block": "White Block", 5 | "item.testmod.translucent_white_block": "Translucent White Block" 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/ResourcePackFinderAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import net.minecraft.resources.IPackFinder; 4 | 5 | import java.util.List; 6 | 7 | public interface ResourcePackFinderAdder { 8 | List getResourcePackFinders(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/BiomeAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import net.minecraft.world.biome.Biome; 4 | 5 | import java.util.Collection; 6 | 7 | public interface BiomeAdder { 8 | void registerBiomes(); 9 | Collection getOverworldBiomes(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/MessageAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import net.minecraft.util.registry.IRegistry; 4 | import org.dimdev.rift.network.Message; 5 | 6 | public interface MessageAdder { 7 | void registerMessages(IRegistry> registry); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/CommandAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import net.minecraft.command.CommandSource; 5 | 6 | public interface CommandAdder { 7 | void registerCommands(CommandDispatcher dispatcher); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/client/KeyBindingAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener.client; 2 | 3 | import net.minecraft.client.settings.KeyBinding; 4 | 5 | import java.util.Collection; 6 | 7 | public interface KeyBindingAdder { 8 | Collection getKeyBindings(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/client/TextureAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener.client; 2 | 3 | import net.minecraft.util.ResourceLocation; 4 | 5 | import java.util.Collection; 6 | 7 | public interface TextureAdder { 8 | Collection getBuiltinTextures(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/ToolEfficiencyProvider.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import net.minecraft.block.Block; 4 | import net.minecraft.item.ItemTool; 5 | 6 | import java.util.Set; 7 | 8 | public interface ToolEfficiencyProvider { 9 | void addEffectiveBlocks(ItemTool tool, Set target); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/injectedmethods/RiftCPacketCustomPayload.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.injectedmethods; 2 | 3 | import net.minecraft.network.PacketBuffer; 4 | import net.minecraft.util.ResourceLocation; 5 | 6 | public interface RiftCPacketCustomPayload { 7 | ResourceLocation getChannelName(); 8 | PacketBuffer getData(); 9 | } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # eclipse 2 | eclipse 3 | bin 4 | *.launch 5 | .settings 6 | .metadata 7 | .classpath 8 | .project 9 | 10 | # idea 11 | out 12 | classes 13 | *.ipr 14 | *.iws 15 | *.iml 16 | .idea 17 | 18 | # gradle 19 | build 20 | .gradle 21 | 22 | #Netbeans 23 | .nb-gradle 24 | .nb-gradle-properties 25 | 26 | # other 27 | run 28 | .DS_Store 29 | Thumbs.db 30 | -------------------------------------------------------------------------------- /src/main/resources/mixins.rift.no_optifine.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "minVersion": "0.7.7", 4 | "compatibilityLevel": "JAVA_8", 5 | "target": "@env(DEFAULT)", 6 | "package": "org.dimdev.rift.mixin.core", 7 | "refmap": "mixins.rift.refmap.json", 8 | "mixins": [ 9 | "MixinVanillaPack" 10 | ], 11 | "client": [ 12 | "client.MixinBlockFluidRenderer" 13 | ] 14 | } -------------------------------------------------------------------------------- /src/main/java/org/dimdev/riftloader/listener/InitializationListener.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.riftloader.listener; 2 | 3 | /** 4 | * This listener is called during the Tweaker initialization phase, before Minecraft 5 | * has started. It allows you to do things like adding tweakers and mixins. 6 | */ 7 | public interface InitializationListener { 8 | void onInitialization(); 9 | } 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: oraclejdk8 3 | 4 | if: tag IS blank 5 | git: 6 | depth: 5 7 | 8 | install: ./gradlew setupCIWorkspace 9 | script: ./gradlew clean build 10 | after_success: ./gradlew publish 11 | 12 | before_cache: find $HOME/.gradle/ -name '*.lock' -print -exec rm -f {} \; 13 | cache: 14 | directories: 15 | - $HOME/.gradle/caches/ 16 | - $HOME/.gradle/wrapper/ 17 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/riftloader/Side.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.riftloader; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public enum Side { 6 | @SerializedName("client") CLIENT, 7 | @SerializedName("server") SERVER, 8 | @SerializedName("both") BOTH; 9 | 10 | public boolean includes(Side side) { 11 | return this == BOTH || this == side; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/mixins.rift.optifine.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "minVersion": "0.7.7", 4 | "compatibilityLevel": "JAVA_8", 5 | "target": "@env(DEFAULT)", 6 | "package": "org.dimdev.rift.mixin.optifine", 7 | "refmap": "mixins.rift.refmap.json", 8 | "mixins": [ 9 | "MixinVanillaPack" 10 | ], 11 | "client": [ 12 | "client.MixinBlockFluidRenderer", 13 | "client.MixinCustomColors" 14 | ] 15 | } -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/RecipeAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import net.minecraft.item.crafting.IRecipe; 4 | import net.minecraft.resources.IResourceManager; 5 | import net.minecraft.util.ResourceLocation; 6 | 7 | import java.util.Map; 8 | 9 | public interface RecipeAdder { 10 | void addRecipes(Map target, IResourceManager resourceManager); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/RecipeSerializerAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import net.minecraft.item.crafting.IRecipeSerializer; 4 | 5 | public interface RecipeSerializerAdder { 6 | /** 7 | * Use {@link net.minecraft.item.crafting.RecipeSerializers#register(IRecipeSerializer)} 8 | * to register new recipe serializers. 9 | */ 10 | void addRecipeSerializers(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/core/MixinMinecraftServer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.core; 2 | 3 | import net.minecraft.server.MinecraftServer; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.Overwrite; 6 | 7 | @Mixin(MinecraftServer.class) 8 | public class MixinMinecraftServer { 9 | @Overwrite 10 | public String getServerModName() { 11 | return "rift"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/riftloader/RiftAccessTransformer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.riftloader; 2 | 3 | import net.minecraft.launchwrapper.IClassTransformer; 4 | 5 | public class RiftAccessTransformer implements IClassTransformer { 6 | @Override 7 | public byte[] transform(String name, String transformedName, byte[] basicClass) { 8 | return RiftLoader.instance.accessTransformer.transformClass(name, basicClass); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/resources/riftmod.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "rift", 3 | "name": "Rift", 4 | "authors": [ 5 | "Runemoro" 6 | ], 7 | "listeners": [ 8 | { 9 | "class": "org.dimdev.rift.Rift", 10 | "side": "both", 11 | "priority": 10 12 | }, { 13 | "class": "org.dimdev.rift.LateRift", 14 | "priority": -10 15 | }, 16 | "org.dimdev.rift.resources.ResourceManager", 17 | "org.dimdev.rift.network.MessageRegistrator" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/client/TileEntityRendererAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener.client; 2 | 3 | import net.minecraft.client.renderer.tileentity.TileEntityRenderer; 4 | import net.minecraft.tileentity.TileEntity; 5 | 6 | import java.util.Map; 7 | 8 | public interface TileEntityRendererAdder { 9 | void addTileEntityRenderers(Map, TileEntityRenderer> renderers); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/util/RegistryUtil.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.util; 2 | 3 | import net.minecraft.util.ResourceLocation; 4 | import net.minecraft.util.registry.IRegistry; 5 | 6 | public class RegistryUtil { 7 | 8 | public static IRegistry createRegistry(ResourceLocation resourceLocation, IRegistry registry) { 9 | IRegistry.REGISTRY.put(resourceLocation, registry); 10 | return registry; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/LateRift.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift; 2 | 3 | import org.dimdev.rift.Rift.RiftTokens; 4 | import org.dimdev.riftloader.listener.InitializationListener; 5 | 6 | import org.spongepowered.asm.mixin.Mixins; 7 | 8 | public class LateRift implements InitializationListener { 9 | 10 | @Override 11 | public void onInitialization() { 12 | if (!RiftTokens.hasOptifine) { 13 | Mixins.addConfiguration("mixins.rift.no_optifine.json"); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/core/client/MixinClientBrandRetriever.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.core.client; 2 | 3 | import net.minecraft.client.ClientBrandRetriever; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.Overwrite; 6 | 7 | @Mixin(ClientBrandRetriever.class) 8 | public class MixinClientBrandRetriever { 9 | @Overwrite 10 | public static String getClientModName() { 11 | return "rift"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/ArgumentTypeAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import net.minecraft.command.arguments.IArgumentSerializer; 4 | import net.minecraft.util.ResourceLocation; 5 | 6 | public interface ArgumentTypeAdder { 7 | /** 8 | * Use {@link net.minecraft.command.arguments.ArgumentTypes#register(ResourceLocation, Class, IArgumentSerializer)} 9 | * to register argument types. 10 | */ 11 | void addArgumentTypes(); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/client/EntityRendererAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener.client; 2 | 3 | import net.minecraft.client.renderer.entity.Render; 4 | import net.minecraft.client.renderer.entity.RenderManager; 5 | import net.minecraft.entity.Entity; 6 | 7 | import java.util.Map; 8 | 9 | public interface EntityRendererAdder { 10 | void addEntityRenderers(Map, Render> entityRenderMap, RenderManager renderManager); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/client/GameGuiAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener.client; 2 | 3 | import net.minecraft.client.entity.EntityPlayerSP; 4 | import net.minecraft.inventory.IInventory; 5 | import net.minecraft.world.IInteractionObject; 6 | 7 | public interface GameGuiAdder { 8 | void displayGui(EntityPlayerSP player, String id, IInteractionObject interactionObject); 9 | void displayContainerGui(EntityPlayerSP player, String id, IInventory inventory); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/resources/mixins.rift.core.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "minVersion": "0.7.7", 4 | "compatibilityLevel": "JAVA_8", 5 | "target": "@env(DEFAULT)", 6 | "package": "org.dimdev.rift.mixin.core", 7 | "refmap": "mixins.rift.refmap.json", 8 | "mixins": [ 9 | "MixinMinecraftServer" 10 | ], 11 | "client": [ 12 | "client.MixinClientBrandRetriever", 13 | "client.MixinLayerArmorBase", 14 | "client.MixinWaterFluid", 15 | "client.MixinLavaFluid", 16 | "client.MixinItemRenderer" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/network/MessageRegistrator.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.network; 2 | 3 | import org.dimdev.rift.listener.BootstrapListener; 4 | import org.dimdev.rift.listener.MessageAdder; 5 | import org.dimdev.riftloader.RiftLoader; 6 | 7 | public class MessageRegistrator implements BootstrapListener { 8 | @Override 9 | public void afterVanillaBootstrap() { 10 | for (MessageAdder messageAdder : RiftLoader.instance.getListeners(MessageAdder.class)) { 11 | messageAdder.registerMessages(Message.REGISTRY); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinStructureIO.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.world.gen.feature.structure.StructureIO; 4 | import org.dimdev.rift.listener.StructureAdder; 5 | import org.dimdev.riftloader.RiftLoader; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | 8 | @Mixin(StructureIO.class) 9 | public class MixinStructureIO { 10 | static { 11 | for (StructureAdder structureAdder : RiftLoader.instance.getListeners(StructureAdder.class)) { 12 | structureAdder.registerStructureNames(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/StructureAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import net.minecraft.world.gen.feature.structure.Structure; 4 | 5 | import java.util.Map; 6 | 7 | public interface StructureAdder { 8 | /** Register structure and structure and peice names in {@link net.minecraft.world.gen.feature.structure.StructureIO}.*/ 9 | void registerStructureNames(); 10 | 11 | /** Add structures to a map between lowercase structure names and structures. See {@link net.minecraft.world.gen.feature.Feature}*/ 12 | void addStructuresToMap(Map> map); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinDimensionType.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.world.dimension.DimensionType; 4 | 5 | import org.dimdev.rift.listener.DimensionTypeAdder; 6 | import org.dimdev.riftloader.RiftLoader; 7 | 8 | import org.spongepowered.asm.mixin.Mixin; 9 | 10 | @Mixin(DimensionType.class) 11 | public class MixinDimensionType { 12 | static { 13 | for (DimensionTypeAdder dimensionTypeAdder : RiftLoader.instance.getListeners(DimensionTypeAdder.class)) { 14 | dimensionTypeAdder.registerDimensionTypes(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinRecipeSerializers.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.item.crafting.RecipeSerializers; 4 | import org.dimdev.rift.listener.RecipeSerializerAdder; 5 | import org.dimdev.riftloader.RiftLoader; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | 8 | @Mixin(RecipeSerializers.class) 9 | public class MixinRecipeSerializers { 10 | static { 11 | for (RecipeSerializerAdder recipeSerializerAdder : RiftLoader.instance.getListeners(RecipeSerializerAdder.class)) { 12 | recipeSerializerAdder.addRecipeSerializers(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/client/AmbientMusicTypeProvider.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener.client; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.util.SoundEvent; 5 | import org.dimdev.utils.ReflectionUtils; 6 | 7 | import static net.minecraft.client.audio.MusicTicker.MusicType; 8 | 9 | public interface AmbientMusicTypeProvider { 10 | static MusicType newMusicType(String name, SoundEvent sound, int minDelay, int maxDelay) { 11 | return ReflectionUtils.makeEnumInstance(MusicType.class, name, -1, sound, minDelay, maxDelay); 12 | } 13 | 14 | MusicType getAmbientMusicType(Minecraft client); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/DimensionTypeAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import net.minecraft.util.ResourceLocation; 4 | import net.minecraft.world.dimension.Dimension; 5 | import net.minecraft.world.dimension.DimensionType; 6 | 7 | import java.util.function.Supplier; 8 | 9 | public interface DimensionTypeAdder { 10 | static DimensionType addDimensionType(int id, ResourceLocation name, String suffix, Supplier dimensionSupplier) { 11 | return DimensionType.register(name.toString(), new DimensionType(id, suffix, name.getPath(), dimensionSupplier)); 12 | } 13 | 14 | void registerDimensionTypes(); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/riftloader/launch/RiftLoaderServerTweaker.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.riftloader.launch; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | public class RiftLoaderServerTweaker extends RiftLoaderTweaker { 8 | @Override 9 | public void acceptOptions(List args, File gameDir, File assetsDir, String profile) { 10 | this.args = new ArrayList<>(args); 11 | 12 | addArg("--version", profile); 13 | } 14 | 15 | @Override 16 | protected boolean isClient() { 17 | return false; 18 | } 19 | 20 | @Override 21 | public String getLaunchTarget() { 22 | return "net.minecraft.server.MinecraftServer"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/chocohead/rift/ClassMapping.java: -------------------------------------------------------------------------------- 1 | package com.chocohead.rift; 2 | 3 | import java.io.Serializable; 4 | import java.util.HashMap; 5 | import java.util.HashSet; 6 | import java.util.Map; 7 | import java.util.Set; 8 | 9 | public class ClassMapping implements Serializable { 10 | private static final long serialVersionUID = -1724841536245456196L; 11 | 12 | public final Set constructors = new HashSet<>(); 13 | public final Map methods = new HashMap<>(); 14 | public final Map fields = new HashMap<>(); 15 | public final String notchName, mcpName; 16 | 17 | public ClassMapping(String notchName, String mcpName) { 18 | this.notchName = notchName; 19 | this.mcpName = mcpName; 20 | } 21 | } -------------------------------------------------------------------------------- /src/main/java/org/dimdev/riftloader/DuplicateModException.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.riftloader; 2 | 3 | public class DuplicateModException extends RuntimeException { 4 | private static final long serialVersionUID = 8227628664058325482L; 5 | 6 | private final ModInfo mod1; 7 | private final ModInfo mod2; 8 | 9 | public DuplicateModException(ModInfo mod1, ModInfo mod2) { 10 | if (!mod1.id.equals(mod2.id)) { 11 | throw new IllegalArgumentException(); 12 | } 13 | 14 | this.mod1 = mod1; 15 | this.mod2 = mod2; 16 | } 17 | 18 | @Override 19 | public String getMessage() { 20 | return "Duplicate mod " + mod1.id + ":\r\n - " + mod1.source + "\r\n - " + mod2.source; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/PacketAdder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import net.minecraft.network.EnumConnectionState; 4 | import net.minecraft.network.EnumPacketDirection; 5 | import net.minecraft.network.Packet; 6 | 7 | public interface PacketAdder { 8 | interface PacketRegistrationReceiver { 9 | EnumConnectionState registerPacket(EnumPacketDirection direction, Class> packetClass); 10 | } 11 | 12 | void registerHandshakingPackets(PacketRegistrationReceiver receiver); 13 | void registerPlayPackets(PacketRegistrationReceiver receiver); 14 | void registerStatusPackets(PacketRegistrationReceiver receiver); 15 | void registerLoginPackets(PacketRegistrationReceiver receiver); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/riftloader/launch/RiftLoaderClientTweaker.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.riftloader.launch; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | public class RiftLoaderClientTweaker extends RiftLoaderTweaker { 8 | @Override 9 | public void acceptOptions(List args, File gameDir, File assetsDir, String profile) { 10 | this.args = new ArrayList<>(args); 11 | 12 | addArg("--version", profile); 13 | addArg("--assetsDir", assetsDir.getPath()); 14 | } 15 | 16 | @Override 17 | public String getLaunchTarget() { 18 | return "net.minecraft.client.main.Main"; 19 | } 20 | 21 | @Override 22 | protected boolean isClient() { 23 | return true; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinItem.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.item.Item; 4 | import org.dimdev.rift.listener.ItemAdder; 5 | import org.dimdev.riftloader.RiftLoader; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | 11 | @Mixin(Item.class) 12 | public abstract class MixinItem { 13 | @Inject(method = "registerItems", at = @At("RETURN")) 14 | private static void onRegisterItems(CallbackInfo ci) { 15 | for (ItemAdder itemAdder : RiftLoader.instance.getListeners(ItemAdder.class)) { 16 | itemAdder.registerItems(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinSoundEvent.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.util.SoundEvent; 4 | import org.dimdev.rift.listener.SoundAdder; 5 | import org.dimdev.riftloader.RiftLoader; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | 11 | @Mixin(SoundEvent.class) 12 | public abstract class MixinSoundEvent { 13 | @Inject(method = "registerSounds", at = @At("RETURN")) 14 | private static void onRegisterSounds(CallbackInfo ci) { 15 | for (SoundAdder soundAdder : RiftLoader.instance.getListeners(SoundAdder.class)) { 16 | soundAdder.registerSounds(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinFeature.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.world.gen.feature.Feature; 4 | import net.minecraft.world.gen.feature.structure.Structure; 5 | import org.dimdev.rift.listener.StructureAdder; 6 | import org.dimdev.riftloader.RiftLoader; 7 | import org.spongepowered.asm.mixin.Final; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | 11 | import java.util.Map; 12 | 13 | @Mixin(Feature.class) 14 | public class MixinFeature { 15 | @Shadow @Final public static Map> STRUCTURES; 16 | 17 | static { 18 | for (StructureAdder structureAdder : RiftLoader.instance.getListeners(StructureAdder.class)) { 19 | structureAdder.addStructuresToMap(STRUCTURES); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinPotion.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.potion.Potion; 4 | import org.dimdev.rift.listener.MobEffectAdder; 5 | import org.dimdev.riftloader.RiftLoader; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | 11 | @Mixin(Potion.class) 12 | public class MixinPotion { 13 | @Inject(method = "registerPotions", at = @At(value = "RETURN")) 14 | private static void onRegisterPotions(CallbackInfo ci) { 15 | for (MobEffectAdder mobEffectAdder : RiftLoader.instance.getListeners(MobEffectAdder.class)) { 16 | mobEffectAdder.registerMobEffects(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/resources/ResourceManager.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.resources; 2 | 3 | import net.minecraft.resources.IPackFinder; 4 | import net.minecraft.resources.ResourcePackType; 5 | import org.dimdev.rift.listener.DataPackFinderAdder; 6 | import org.dimdev.rift.listener.ResourcePackFinderAdder; 7 | 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | public class ResourceManager implements ResourcePackFinderAdder, DataPackFinderAdder { 12 | @Override 13 | public List getResourcePackFinders() { 14 | return Collections.singletonList(new ModPackFinder(ResourcePackType.CLIENT_RESOURCES)); 15 | } 16 | 17 | @Override public List getDataPackFinders() { 18 | return Collections.singletonList(new ModPackFinder(ResourcePackType.SERVER_DATA)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinCPacketCustomPayload.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.network.PacketBuffer; 4 | import net.minecraft.network.play.client.CPacketCustomPayload; 5 | import net.minecraft.util.ResourceLocation; 6 | import org.dimdev.rift.injectedmethods.RiftCPacketCustomPayload; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | 10 | @Mixin(CPacketCustomPayload.class) 11 | public class MixinCPacketCustomPayload implements RiftCPacketCustomPayload { 12 | @Shadow private ResourceLocation channel; 13 | @Shadow private PacketBuffer data; 14 | 15 | @Override 16 | public ResourceLocation getChannelName() { 17 | return channel; 18 | } 19 | 20 | @Override 21 | public PacketBuffer getData() { 22 | return data; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/client/MixinGuiIngame.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook.client; 2 | 3 | import net.minecraft.client.gui.GuiIngame; 4 | import org.dimdev.rift.listener.client.OverlayRenderer; 5 | import org.dimdev.riftloader.RiftLoader; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | 11 | @Mixin(GuiIngame.class) 12 | public class MixinGuiIngame { 13 | @Inject(method = "renderGameOverlay", at = @At("RETURN")) 14 | private void onRenderGameOverlay(CallbackInfo ci) { 15 | for (OverlayRenderer overlayRenderer : RiftLoader.instance.getListeners(OverlayRenderer.class)) { 16 | overlayRenderer.renderOverlay(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinEnchantment.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.enchantment.Enchantment; 4 | import org.dimdev.rift.listener.EnchantmentAdder; 5 | import org.dimdev.riftloader.RiftLoader; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | 11 | @Mixin(Enchantment.class) 12 | public class MixinEnchantment { 13 | @Inject(method = "registerEnchantments", at = @At(value = "RETURN")) 14 | private static void onRegisterEnchantments(CallbackInfo ci) { 15 | for (EnchantmentAdder enchantmentAdder : RiftLoader.instance.getListeners(EnchantmentAdder.class)) { 16 | enchantmentAdder.registerEnchantments(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinParticleType.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.particles.ParticleType; 4 | import org.dimdev.rift.listener.ParticleTypeAdder; 5 | import org.dimdev.riftloader.RiftLoader; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | 11 | @Mixin(ParticleType.class) 12 | public abstract class MixinParticleType { 13 | @Inject(method = "registerAll", at = @At("RETURN")) 14 | private static void onRegisterParticleTypes(CallbackInfo ci) { 15 | for (ParticleTypeAdder particleTypeAdder : RiftLoader.instance.getListeners(ParticleTypeAdder.class)) { 16 | particleTypeAdder.registerParticles(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/client/MixinModelBakery.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook.client; 2 | 3 | import net.minecraft.client.renderer.model.ModelBakery; 4 | import net.minecraft.util.ResourceLocation; 5 | import org.dimdev.rift.listener.client.TextureAdder; 6 | import org.dimdev.riftloader.RiftLoader; 7 | import org.spongepowered.asm.mixin.Final; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | 11 | import java.util.Set; 12 | 13 | @Mixin(ModelBakery.class) 14 | public class MixinModelBakery { 15 | @Shadow @Final private static Set LOCATIONS_BUILTIN_TEXTURES; 16 | 17 | static { 18 | for (TextureAdder textureAdder : RiftLoader.instance.getListeners(TextureAdder.class)) { 19 | LOCATIONS_BUILTIN_TEXTURES.addAll(textureAdder.getBuiltinTextures()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/util/NBTSerializer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.util; 2 | 3 | import net.minecraft.nbt.NBTTagCompound; 4 | 5 | import javax.annotation.Nonnull; 6 | 7 | /** 8 | * Base interface for (de)serializing objects of type {@code T} 9 | * to and from {@link NBTTagCompound} tag compounds 10 | */ 11 | public interface NBTSerializer { 12 | /** 13 | * Writes an object {@code T} to the given compound 14 | * @param instance The instance to be serialized 15 | * @return The written tag compound 16 | */ 17 | @Nonnull 18 | NBTTagCompound serialize(@Nonnull T instance); 19 | 20 | /** 21 | * Reads an object {@code T} from the given compound 22 | * @param compound The tag compound to be read from 23 | * @return An instance of {@code T} 24 | */ 25 | @Nonnull 26 | T deserialize(@Nonnull NBTTagCompound compound); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinArgumentTypes.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.command.arguments.ArgumentTypes; 4 | import org.dimdev.rift.listener.ArgumentTypeAdder; 5 | import org.dimdev.riftloader.RiftLoader; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | 11 | @Mixin(ArgumentTypes.class) 12 | public class MixinArgumentTypes { 13 | @Inject(method = "registerArgumentTypes", at = @At("RETURN")) 14 | private static void onRegisterArgumentTypes(CallbackInfo ci) { 15 | for (ArgumentTypeAdder argumentTypeAdder : RiftLoader.instance.getListeners(ArgumentTypeAdder.class)) { 16 | argumentTypeAdder.addArgumentTypes(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinFluid.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.fluid.Fluid; 4 | import org.dimdev.rift.listener.FluidAdder; 5 | import org.dimdev.riftloader.RiftLoader; 6 | import org.objectweb.asm.Opcodes; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.injection.At; 9 | import org.spongepowered.asm.mixin.injection.Inject; 10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 11 | 12 | @Mixin(Fluid.class) 13 | public abstract class MixinFluid { 14 | @Inject(method = "registerAll", at = @At(value = "FIELD", target = "Lnet/minecraft/util/registry/IRegistry;FLUID:Lnet/minecraft/util/registry/IRegistry;", opcode = Opcodes.GETSTATIC, ordinal = 1)) 15 | private static void onRegisterFluids(CallbackInfo ci) { 16 | for (FluidAdder fluidAdder : RiftLoader.instance.getListeners(FluidAdder.class)) { 17 | fluidAdder.registerFluids(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinFurnace.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.item.Item; 4 | import net.minecraft.tileentity.TileEntityFurnace; 5 | import org.dimdev.rift.listener.BurnTimeProvider; 6 | import org.dimdev.riftloader.RiftLoader; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.injection.At; 9 | import org.spongepowered.asm.mixin.injection.Inject; 10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 11 | 12 | import java.util.Map; 13 | 14 | @Mixin(TileEntityFurnace.class) 15 | public class MixinFurnace { 16 | @Inject(method = "getBurnTimes", at = @At(value = "RETURN")) 17 | private static void getBurnTimes(CallbackInfoReturnable> cir) { 18 | for (BurnTimeProvider burnTimeProvider : RiftLoader.instance.getListeners(BurnTimeProvider.class)) { 19 | burnTimeProvider.registerBurnTimes(cir.getReturnValue()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinBlock.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.block.Block; 4 | 5 | import org.dimdev.rift.listener.BlockAdder; 6 | import org.dimdev.riftloader.RiftLoader; 7 | 8 | import org.objectweb.asm.Opcodes; 9 | 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 14 | 15 | @Mixin(Block.class) 16 | public abstract class MixinBlock { 17 | @Inject(method = "registerBlocks", at = @At(value = "FIELD", target = "Lnet/minecraft/util/registry/IRegistry;BLOCK:Lnet/minecraft/util/registry/IRegistry;", opcode = Opcodes.GETSTATIC, ordinal = 1)) 18 | private static void onRegisterBlocks(CallbackInfo ci) { 19 | for (BlockAdder blockAdder : RiftLoader.instance.getListeners(BlockAdder.class)) { 20 | blockAdder.registerBlocks(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/riftloader/listener/Instantiator.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.riftloader.listener; 2 | 3 | /** 4 | * Allows mods to provide ways to create instances of classes which don't 5 | * have a public no-args constructor. 6 | *

7 | * A class implementing the instantiator interface must necessarily contain 8 | * a public no-args constructor, to prevent infinite recursion while attempting 9 | * to create an instance of it. 10 | */ 11 | public interface Instantiator { 12 | /** 13 | * Creates an instance of a certain class, or null if the instantiator 14 | * can't handle it. 15 | * 16 | * @param clazz class to instantiate 17 | * @return an instance of listenerClass, or null to skip this instantiator 18 | * @throws ReflectiveOperationException if the instantiator can handle this type of class, 19 | * but an error occured during instantiation 20 | */ 21 | T newInstance(Class clazz) throws ReflectiveOperationException; 22 | } 23 | -------------------------------------------------------------------------------- /src/debug/java/org/dimdev/testmod/CPacketTest.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.testmod; 2 | 3 | import net.minecraft.network.Packet; 4 | import net.minecraft.network.PacketBuffer; 5 | import net.minecraft.network.play.INetHandlerPlayServer; 6 | import org.apache.logging.log4j.LogManager; 7 | import org.apache.logging.log4j.Logger; 8 | 9 | public class CPacketTest implements Packet { 10 | private static final Logger log = LogManager.getLogger(); 11 | private int data; 12 | 13 | public CPacketTest() {} 14 | 15 | public CPacketTest(int data) { 16 | this.data = data; 17 | } 18 | 19 | @Override 20 | public void readPacketData(PacketBuffer buf) { 21 | data = buf.readVarInt(); 22 | } 23 | 24 | @Override 25 | public void writePacketData(PacketBuffer buf) { 26 | buf.writeVarInt(data); 27 | } 28 | 29 | @Override 30 | public void processPacket(INetHandlerPlayServer handler) { 31 | log.info("Server received test packet: " + data); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/injectedmethods/RiftFluid.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.injectedmethods; 2 | 3 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 4 | import net.minecraft.util.math.BlockPos; 5 | import net.minecraft.world.IWorldReader; 6 | 7 | public interface RiftFluid { 8 | TextureAtlasSprite getStillTexture(); 9 | TextureAtlasSprite getFlowingTexture(); 10 | int getColorMultiplier(IWorldReader world, BlockPos pos); 11 | 12 | /** 13 | * Optifine changes how fluid colouring is calculated, returning true reverts this back to what {@link RiftFluid#getColorMultiplier(IWorldReader, BlockPos)} returns. 14 | *
15 | * When Optifine is not present this method is unused and {@link RiftFluid#getColorMultiplier(IWorldReader, BlockPos)} is always used. 16 | * 17 | * @return Whether to rely on the colour Optifine works out (if present) or use {@link RiftFluid#getColorMultiplier(IWorldReader, BlockPos)} 18 | */ 19 | default boolean ignoreOptifine() { 20 | return true; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/utils/InstanceListMap.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.utils; 2 | 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | public class InstanceListMap { // Type-safe map between classes and instances 8 | private Map, List> uncheckedMap = new HashMap<>(); 9 | 10 | public void put(Class key, List value) { 11 | uncheckedMap.put(key, value); 12 | } 13 | 14 | public List get(Class key) { 15 | //noinspection unchecked 16 | return (List) uncheckedMap.get(key); 17 | } 18 | 19 | public List remove(Class key) { 20 | //noinspection unchecked 21 | return (List) uncheckedMap.remove(key); 22 | } 23 | 24 | public void clear() { 25 | uncheckedMap.clear(); 26 | } 27 | 28 | public boolean containsKey(Class key) { 29 | return uncheckedMap.containsKey(key); 30 | } 31 | 32 | public boolean containsValue(List value) { 33 | return uncheckedMap.containsValue(value); 34 | } 35 | } -------------------------------------------------------------------------------- /src/debug/java/org/dimdev/testmod/ItemPacketTester.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.testmod; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.item.Item; 5 | import net.minecraft.item.ItemUseContext; 6 | import net.minecraft.util.EnumActionResult; 7 | import org.apache.logging.log4j.LogManager; 8 | import org.apache.logging.log4j.Logger; 9 | 10 | public class ItemPacketTester extends Item { 11 | private static final Logger log = LogManager.getLogger(); 12 | 13 | public ItemPacketTester(Properties builder) { 14 | super(builder); 15 | } 16 | 17 | @Override 18 | public EnumActionResult onItemUse(ItemUseContext context) { 19 | if (context.getWorld().isRemote) { 20 | return EnumActionResult.SUCCESS; 21 | } 22 | 23 | int data = (int) (Math.random() * 1000); 24 | log.info("Sending test packet and message to server: " + data); 25 | Minecraft.getInstance().getConnection().sendPacket(new CPacketTest(data)); 26 | 27 | new TestMessage(data).sendToServer(); 28 | 29 | return EnumActionResult.SUCCESS; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/network/ServerMessageContext.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.network; 2 | 3 | import net.minecraft.entity.player.EntityPlayerMP; 4 | import net.minecraft.network.NetworkManager; 5 | import net.minecraft.server.MinecraftServer; 6 | 7 | public class ServerMessageContext implements MessageContext { 8 | private final MinecraftServer server; 9 | private final EntityPlayerMP sender; 10 | private final NetworkManager networkManager; 11 | 12 | public ServerMessageContext(MinecraftServer server, EntityPlayerMP sender, NetworkManager networkManager) { 13 | this.server = server; 14 | this.sender = sender; 15 | this.networkManager = networkManager; 16 | } 17 | 18 | public MinecraftServer getServer() { 19 | return server; 20 | } 21 | 22 | public EntityPlayerMP getSender() { 23 | return sender; 24 | } 25 | 26 | @Override 27 | public NetworkManager getNetworkManager() { 28 | return networkManager; 29 | } 30 | 31 | @Override 32 | public void reply(Message message) { 33 | message.send(sender); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/utils/InstanceMap.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.utils; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class InstanceMap { // Type-safe map between classes and instances 7 | private Map, Object> uncheckedMap = new HashMap<>(); 8 | 9 | public void put(Class key, T value) { 10 | uncheckedMap.put(key, value); 11 | } 12 | 13 | public void castAndPut(Class key, Object value) { 14 | uncheckedMap.put(key, key.cast(value)); 15 | } 16 | 17 | public T get(Class key) { 18 | //noinspection unchecked 19 | return (T) uncheckedMap.get(key); 20 | } 21 | 22 | public T remove(Class key) { 23 | //noinspection unchecked 24 | return (T) uncheckedMap.remove(key); 25 | } 26 | 27 | public void clear() { 28 | uncheckedMap.clear(); 29 | } 30 | 31 | public boolean containsKey(Class key) { 32 | return uncheckedMap.containsKey(key); 33 | } 34 | 35 | public boolean containsValue(Object value) { 36 | return uncheckedMap.containsValue(value); 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinChunk.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.world.chunk.Chunk; 4 | import org.dimdev.rift.listener.ChunkEventListener; 5 | import org.dimdev.riftloader.RiftLoader; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | 11 | @Mixin(Chunk.class) 12 | public class MixinChunk { 13 | @Inject(method = "onLoad", at = @At("RETURN")) 14 | private void onChunkLoad(CallbackInfo ci) { 15 | for (ChunkEventListener listener : RiftLoader.instance.getListeners(ChunkEventListener.class)) { 16 | listener.onChunkLoad((Chunk) (Object) this); 17 | } 18 | } 19 | 20 | @Inject(method = "onUnload", at = @At("RETURN")) 21 | private void onChunkUnoad(CallbackInfo ci) { 22 | for (ChunkEventListener listener : RiftLoader.instance.getListeners(ChunkEventListener.class)) { 23 | listener.onChunkUnload((Chunk) (Object) this); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Dimensional Development 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/core/client/MixinItemRenderer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.core.client; 2 | 3 | import org.spongepowered.asm.mixin.Mixin; 4 | import org.spongepowered.asm.mixin.injection.At; 5 | import org.spongepowered.asm.mixin.injection.Redirect; 6 | 7 | import net.minecraft.client.renderer.ItemRenderer; 8 | import net.minecraft.item.Item; 9 | import net.minecraft.util.ResourceLocation; 10 | import net.minecraft.util.registry.IRegistry; 11 | 12 | @Mixin(ItemRenderer.class) 13 | public class MixinItemRenderer { 14 | @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/registry/IRegistry;getKey(Ljava/lang/Object;)Lnet/minecraft/util/ResourceLocation;")) 15 | private ResourceLocation onGetItem(IRegistry registry, Object item) { 16 | ResourceLocation key = registry.getKey(item); 17 | 18 | if (key == null) { 19 | //Guard against unregistered items to avoid throwing unhelpful NPEs in ModelResourceLocation's constructor 20 | throw new IllegalStateException("Item registered with null key: " + item + " - " + ((Item) item).getName() + " (" + item.getClass() + ')'); 21 | } else { 22 | return key; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/util/NBTSerializable.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.util; 2 | 3 | import net.minecraft.nbt.NBTTagCompound; 4 | 5 | import javax.annotation.Nonnull; 6 | 7 | /** 8 | * Base interface for (de)serializable objects to serialize 9 | * themselves to and from {@link NBTTagCompound} tag compounds 10 | */ 11 | public interface NBTSerializable { 12 | /** 13 | * Writes this object's data to the given compound 14 | * @param compound The tag compound to be written to 15 | * @return The written tag compound 16 | */ 17 | @Nonnull 18 | NBTTagCompound serialize(@Nonnull NBTTagCompound compound); 19 | 20 | /** 21 | * Reads this object's data from the given compound 22 | * @param compound The tag compound to be read from 23 | * @return The given tag compound 24 | */ 25 | @Nonnull 26 | NBTTagCompound deserialize(@Nonnull NBTTagCompound compound); 27 | 28 | /** 29 | * Writes this object's data to a new tag compound 30 | * @return The written tag compound 31 | */ 32 | @Nonnull 33 | default NBTTagCompound writeToNBT() { 34 | return this.serialize(new NBTTagCompound()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinCommands.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import com.mojang.brigadier.AmbiguityConsumer; 4 | import com.mojang.brigadier.CommandDispatcher; 5 | import net.minecraft.command.CommandSource; 6 | import net.minecraft.command.Commands; 7 | import org.dimdev.rift.listener.CommandAdder; 8 | import org.dimdev.riftloader.RiftLoader; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.injection.At; 11 | import org.spongepowered.asm.mixin.injection.Redirect; 12 | 13 | @Mixin(Commands.class) 14 | public class MixinCommands { 15 | // Workaround for https://github.com/SpongePowered/Mixin/issues/267 16 | @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/CommandDispatcher;findAmbiguities(Lcom/mojang/brigadier/AmbiguityConsumer;)V", remap = false)) 17 | public void findAmbiguities(CommandDispatcher dispatcher, AmbiguityConsumer consumer) { 18 | for (CommandAdder commandAdder : RiftLoader.instance.getListeners(CommandAdder.class)) { 19 | commandAdder.registerCommands(dispatcher); 20 | } 21 | dispatcher.findAmbiguities(consumer); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/resources/profile.json: -------------------------------------------------------------------------------- 1 | { 2 | "inheritsFrom": "1.13.2", 3 | "id": "1.13.2-rift-${version}", 4 | "releaseTime": "2018-11-29T09:45:00+00:00", 5 | "time": "2018-11-29T09:50:00+00:00", 6 | "type": "release", 7 | "arguments": { 8 | "game": [ 9 | "--tweakClass", 10 | "org.dimdev.riftloader.launch.RiftLoaderClientTweaker" 11 | ] 12 | }, 13 | "mainClass": "net.minecraft.launchwrapper.Launch", 14 | "libraries": [ 15 | { 16 | "name": "com.github.Chocohead:Rift:${build}", 17 | "url": "https://www.jitpack.io/" 18 | }, 19 | { 20 | "name": "org.dimdev:mixin:0.7.11-SNAPSHOT", 21 | "url": "https://www.dimdev.org/maven/" 22 | }, 23 | { 24 | "name": "org.ow2.asm:asm:6.2", 25 | "url": "http://repo1.maven.org/maven2/" 26 | }, 27 | { 28 | "name": "org.ow2.asm:asm-commons:6.2", 29 | "url": "http://repo1.maven.org/maven2/" 30 | }, 31 | { 32 | "name": "org.ow2.asm:asm-tree:6.2", 33 | "url": "http://repo1.maven.org/maven2/" 34 | }, 35 | { 36 | "name": "net.minecraft:launchwrapper:1.12" 37 | } 38 | ] 39 | } -------------------------------------------------------------------------------- /src/debug/java/org/dimdev/testmod/TestMessage.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.testmod; 2 | 3 | import net.minecraft.network.PacketBuffer; 4 | import org.dimdev.rift.network.ClientMessageContext; 5 | import org.dimdev.rift.network.Message; 6 | import org.dimdev.rift.network.ServerMessageContext; 7 | 8 | public class TestMessage extends Message { 9 | public int data; 10 | 11 | public TestMessage() {} 12 | 13 | public TestMessage(int data) { 14 | this.data = data; 15 | } 16 | 17 | @Override 18 | public void write(PacketBuffer buffer) { 19 | buffer.writeVarInt(data); 20 | } 21 | 22 | @Override 23 | public void read(PacketBuffer buffer) { 24 | data = buffer.readVarInt(); 25 | } 26 | 27 | @Override 28 | public void process(ClientMessageContext context) { 29 | System.out.println("Received message on client: " + data); 30 | 31 | if (Math.random() < 0.5) { 32 | context.reply(new TestMessage(data + 1)); 33 | } 34 | } 35 | 36 | @Override 37 | public void process(ServerMessageContext context) { 38 | System.out.println("Received message on server: " + data); 39 | 40 | if (Math.random() < 0.5) { 41 | context.reply(new TestMessage(data + 1)); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/core/client/MixinLavaFluid.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.core.client; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.renderer.model.ModelBakery; 5 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 6 | import net.minecraft.fluid.LavaFluid; 7 | import net.minecraft.init.Blocks; 8 | import net.minecraft.util.math.BlockPos; 9 | import net.minecraft.world.IWorldReader; 10 | import org.dimdev.rift.injectedmethods.RiftFluid; 11 | import org.spongepowered.asm.mixin.Mixin; 12 | 13 | @Mixin(LavaFluid.class) 14 | public class MixinLavaFluid implements RiftFluid { 15 | @Override 16 | public TextureAtlasSprite getStillTexture() { 17 | return Minecraft.getInstance().getModelManager().getBlockModelShapes().getModel(Blocks.LAVA.getDefaultState()).getParticleTexture(); 18 | } 19 | 20 | @Override 21 | public TextureAtlasSprite getFlowingTexture() { 22 | return Minecraft.getInstance().getTextureMap().getSprite(ModelBakery.LOCATION_LAVA_FLOW); 23 | } 24 | 25 | @Override 26 | public int getColorMultiplier(IWorldReader world, BlockPos pos) { 27 | return 0xFFFFFF; 28 | } 29 | 30 | @Override 31 | public boolean ignoreOptifine() { 32 | return false; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinRecipeManager.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.item.crafting.IRecipe; 4 | import net.minecraft.item.crafting.RecipeManager; 5 | import net.minecraft.resources.IResourceManager; 6 | import net.minecraft.util.ResourceLocation; 7 | import org.dimdev.rift.listener.RecipeAdder; 8 | import org.dimdev.riftloader.RiftLoader; 9 | import org.spongepowered.asm.mixin.Final; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | import org.spongepowered.asm.mixin.injection.At; 13 | import org.spongepowered.asm.mixin.injection.Inject; 14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 15 | 16 | import java.util.Map; 17 | 18 | @Mixin(RecipeManager.class) 19 | public class MixinRecipeManager { 20 | @Shadow @Final private Map recipes; 21 | 22 | @Inject(method = "onResourceManagerReload", at = @At(value = "INVOKE", target = "Ljava/util/Map;size()I", remap = false)) 23 | private void onLoadRecipes(IResourceManager resourceManager, CallbackInfo ci) { 24 | for (RecipeAdder recipeAdder : RiftLoader.instance.getListeners(RecipeAdder.class)) { 25 | recipeAdder.addRecipes(recipes, resourceManager); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinBiome.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.world.biome.Biome; 4 | import org.dimdev.rift.listener.BiomeAdder; 5 | import org.dimdev.rift.listener.WorldChanger; 6 | import org.dimdev.riftloader.RiftLoader; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.injection.At; 9 | import org.spongepowered.asm.mixin.injection.Inject; 10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 11 | 12 | @Mixin(Biome.class) 13 | public abstract class MixinBiome { 14 | @Inject(method = "registerBiomes", at = @At(value = "INVOKE", target = "Ljava/util/Collections;addAll(Ljava/util/Collection;[Ljava/lang/Object;)Z", remap = false)) 15 | private static void onRegisterBiomes(CallbackInfo ci) { 16 | for (BiomeAdder biomeAdder : RiftLoader.instance.getListeners(BiomeAdder.class)) { 17 | biomeAdder.registerBiomes(); 18 | } 19 | } 20 | 21 | @Inject(method = "register", at = @At(value = "RETURN")) 22 | private static void onRegisterBiome(int biomeId, String biomeName, Biome biome, CallbackInfo ci) { 23 | for (WorldChanger worldChanger : RiftLoader.instance.getListeners(WorldChanger.class)) { 24 | worldChanger.modifyBiome(biomeId, biomeName, biome); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/client/MixinGameSettings.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook.client; 2 | 3 | import net.minecraft.client.GameSettings; 4 | import net.minecraft.client.settings.KeyBinding; 5 | import org.dimdev.rift.listener.client.KeyBindingAdder; 6 | import org.dimdev.riftloader.RiftLoader; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | import org.spongepowered.asm.mixin.injection.Inject; 11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 12 | 13 | import java.util.ArrayList; 14 | import java.util.Collections; 15 | import java.util.List; 16 | 17 | @Mixin(GameSettings.class) 18 | public class MixinGameSettings { 19 | @Shadow public KeyBinding[] keyBindings; 20 | 21 | @Inject(method = "loadOptions", at = @At("HEAD")) 22 | private void onLoadOptions(CallbackInfo ci) { 23 | List keyBindingList = new ArrayList<>(keyBindings.length); 24 | Collections.addAll(keyBindingList, keyBindings); 25 | for (KeyBindingAdder keyBindingAdder : RiftLoader.instance.getListeners(KeyBindingAdder.class)) { 26 | keyBindingList.addAll(keyBindingAdder.getKeyBindings()); 27 | } 28 | keyBindings = keyBindingList.toArray(new KeyBinding[0]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinOverworldBiomeProvider.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.world.biome.Biome; 4 | import net.minecraft.world.biome.provider.OverworldBiomeProvider; 5 | import org.dimdev.rift.listener.BiomeAdder; 6 | import org.dimdev.riftloader.RiftLoader; 7 | import org.spongepowered.asm.mixin.Final; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Mutable; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 14 | 15 | import java.util.ArrayList; 16 | import java.util.Arrays; 17 | import java.util.List; 18 | 19 | @Mixin(OverworldBiomeProvider.class) 20 | public abstract class MixinOverworldBiomeProvider { 21 | @Shadow @Final @Mutable private Biome[] biomes; 22 | 23 | @Inject(method = "", at = @At("RETURN")) 24 | private void onInit(CallbackInfo ci) { 25 | List biomes = new ArrayList<>(Arrays.asList(this.biomes)); 26 | for (BiomeAdder biomeAdder : RiftLoader.instance.getListeners(BiomeAdder.class)) { 27 | biomes.addAll(biomeAdder.getOverworldBiomes()); 28 | } 29 | 30 | this.biomes = biomes.toArray(new Biome[0]); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/core/client/MixinWaterFluid.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.core.client; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.renderer.model.ModelBakery; 5 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 6 | import net.minecraft.fluid.WaterFluid; 7 | import net.minecraft.init.Blocks; 8 | import net.minecraft.util.math.BlockPos; 9 | import net.minecraft.world.IWorldReader; 10 | import net.minecraft.world.biome.BiomeColors; 11 | import org.dimdev.rift.injectedmethods.RiftFluid; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | 14 | @Mixin(WaterFluid.class) 15 | public class MixinWaterFluid implements RiftFluid { 16 | @Override 17 | public TextureAtlasSprite getStillTexture() { 18 | return Minecraft.getInstance().getModelManager().getBlockModelShapes().getModel(Blocks.WATER.getDefaultState()).getParticleTexture(); 19 | } 20 | 21 | @Override 22 | public TextureAtlasSprite getFlowingTexture() { 23 | return Minecraft.getInstance().getTextureMap().getSprite(ModelBakery.LOCATION_WATER_FLOW); 24 | } 25 | 26 | @Override 27 | public int getColorMultiplier(IWorldReader world, BlockPos pos) { 28 | return BiomeColors.getWaterColor(world, pos); 29 | } 30 | 31 | @Override 32 | public boolean ignoreOptifine() { 33 | return false; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/client/MixinRenderManager.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook.client; 2 | 3 | import net.minecraft.client.renderer.ItemRenderer; 4 | import net.minecraft.client.renderer.entity.Render; 5 | import net.minecraft.client.renderer.entity.RenderManager; 6 | import net.minecraft.client.renderer.texture.TextureManager; 7 | import net.minecraft.entity.Entity; 8 | import org.dimdev.rift.listener.client.EntityRendererAdder; 9 | import org.dimdev.riftloader.RiftLoader; 10 | import org.spongepowered.asm.mixin.Final; 11 | import org.spongepowered.asm.mixin.Mixin; 12 | import org.spongepowered.asm.mixin.Shadow; 13 | import org.spongepowered.asm.mixin.injection.At; 14 | import org.spongepowered.asm.mixin.injection.Inject; 15 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 16 | 17 | import java.util.Map; 18 | 19 | @Mixin(RenderManager.class) 20 | public class MixinRenderManager { 21 | @Shadow @Final private Map, Render> entityRenderMap; 22 | 23 | @Inject(method = "", at = @At("RETURN")) 24 | private void onInit(TextureManager textureManager, ItemRenderer itemRenderer, CallbackInfo ci) { 25 | for (EntityRendererAdder entityRendererAdder : RiftLoader.instance.getListeners(EntityRendererAdder.class)) { 26 | entityRendererAdder.addEntityRenderers(entityRenderMap, (RenderManager) (Object) this); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/listener/ChunkGeneratorReplacer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.listener; 2 | 3 | import net.minecraft.world.WorldServer; 4 | import net.minecraft.world.WorldType; 5 | import net.minecraft.world.gen.ChunkGeneratorType; 6 | import net.minecraft.world.gen.IChunkGenSettings; 7 | import net.minecraft.world.gen.IChunkGenerator; 8 | 9 | import javax.annotation.Nullable; 10 | import java.util.function.Supplier; 11 | 12 | /** 13 | * used to substitute custom {@link IChunkGenerator}s for vanilla ones
14 | * NOTE:
15 | * custom {@link WorldType}s are registered by just instantiating them
16 | * custom {@link ChunkGeneratorType}s are registered via {@link ChunkGeneratorType#registerChunkGeneratorType(String, IChunkGeneratorFactory, ChunkGeneratorType.Settings, boolean)}
17 | * custom {@link ChunkGeneratorType.Settings} are registered via {@link ChunkGeneratorType.Settings#registerChunkGeneratorSettings(String, Supplier)} 18 | */ 19 | public interface ChunkGeneratorReplacer { 20 | 21 | /** 22 | * create an {@link IChunkGenerator} for your world type 23 | * @param worldType the world type that is currently set 24 | * @return a custom chunk generator or {@code null} to fall back to vanilla chunk generator selection 25 | */ 26 | @Nullable 27 | IChunkGenerator createChunkGenerator(WorldServer world, WorldType worldType, int dimensionID); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/accesstransform/AccessLevel.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.accesstransform; 2 | 3 | import java.util.Locale; 4 | 5 | public class AccessLevel { 6 | public enum Visibility { 7 | PRIVATE, 8 | DEFAULT, 9 | PROTECTED, 10 | PUBLIC 11 | } 12 | 13 | public final Visibility visibility; 14 | public final boolean isFinal; 15 | 16 | public AccessLevel(Visibility visibility, boolean isFinal) { 17 | this.visibility = visibility; 18 | this.isFinal = isFinal; 19 | } 20 | 21 | public static AccessLevel union(AccessLevel first, AccessLevel second) { 22 | if (first == null) { 23 | return second; 24 | } else if (second == null) { 25 | return first; 26 | } 27 | 28 | Visibility visibility = first.visibility.ordinal() < second.visibility.ordinal() ? second.visibility : first.visibility; 29 | boolean isFinal = first.isFinal && second.isFinal; 30 | 31 | return new AccessLevel(visibility, isFinal); 32 | } 33 | 34 | public static AccessLevel fromString(String string) { 35 | string = string.toUpperCase(Locale.ROOT); 36 | boolean isFinal = true; 37 | if (string.endsWith("-F")) { 38 | isFinal = false; 39 | string = string.substring(0, string.length() - 2); 40 | } 41 | 42 | return new AccessLevel(Visibility.valueOf(string), isFinal); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/optifine/client/MixinCustomColors.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.optifine.client; 2 | 3 | import org.dimdev.rift.injectedmethods.RiftFluid; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.injection.At; 6 | import org.spongepowered.asm.mixin.injection.Coerce; 7 | import org.spongepowered.asm.mixin.injection.Inject; 8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 9 | 10 | import net.minecraft.block.state.IBlockState; 11 | import net.minecraft.fluid.IFluidState; 12 | import net.minecraft.util.math.BlockPos; 13 | import net.minecraft.world.IWorldReader; 14 | 15 | @Mixin(targets = "net/optifine/CustomColors") 16 | public class MixinCustomColors { 17 | @Inject(at = @At("RETURN"), method = "getFluidColor(Lnet/minecraft/world/IWorldReader;Lnet/minecraft/block/state/IBlockState;Lnet/minecraft/util/math/BlockPos;Lnet/optifine/render/RenderEnv;)I", cancellable = true, remap = true, constraints = "OPTIFINE(1+)") 18 | private static void fixFluidColours(IWorldReader world, IBlockState state, BlockPos pos, @Coerce Object renderEnv, CallbackInfoReturnable callback) { 19 | IFluidState fluidState = world.getFluidState(pos); 20 | 21 | if (fluidState.getFluid() instanceof RiftFluid) { 22 | RiftFluid fluid = (RiftFluid) fluidState.getFluid(); 23 | if (fluid.ignoreOptifine()) callback.setReturnValue(fluid.getColorMultiplier(world, pos)); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinItemTool.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.block.Block; 4 | import net.minecraft.item.IItemTier; 5 | import net.minecraft.item.Item; 6 | import net.minecraft.item.ItemTool; 7 | import org.dimdev.rift.listener.ToolEfficiencyProvider; 8 | import org.dimdev.riftloader.RiftLoader; 9 | import org.spongepowered.asm.mixin.Final; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Mutable; 12 | import org.spongepowered.asm.mixin.Shadow; 13 | import org.spongepowered.asm.mixin.injection.At; 14 | import org.spongepowered.asm.mixin.injection.Inject; 15 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 16 | 17 | import java.util.HashSet; 18 | import java.util.Set; 19 | 20 | @Mixin(ItemTool.class) 21 | public class MixinItemTool { 22 | @Shadow @Mutable @Final private Set effectiveBlocks; 23 | 24 | @Inject(method = "", at = @At("RETURN")) 25 | private void onInit(float attackDamage, float attackSpeed, IItemTier tier, Set effectiveBlocks, Item.Properties builder, CallbackInfo ci) { 26 | this.effectiveBlocks = new HashSet<>(effectiveBlocks); 27 | 28 | for (ToolEfficiencyProvider toolEfficiencyProvider : RiftLoader.instance.getListeners(ToolEfficiencyProvider.class)) { 29 | toolEfficiencyProvider.addEffectiveBlocks((ItemTool) (Object) this, this.effectiveBlocks); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinAnvilSaveHandler.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import com.mojang.datafixers.DataFixer; 4 | import net.minecraft.server.MinecraftServer; 5 | import net.minecraft.world.chunk.storage.AnvilChunkLoader; 6 | import net.minecraft.world.chunk.storage.AnvilSaveHandler; 7 | import net.minecraft.world.chunk.storage.IChunkLoader; 8 | import net.minecraft.world.dimension.Dimension; 9 | import net.minecraft.world.storage.SaveHandler; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Overwrite; 12 | 13 | import javax.annotation.Nullable; 14 | import java.io.File; 15 | 16 | @Mixin(AnvilSaveHandler.class) 17 | public class MixinAnvilSaveHandler extends SaveHandler { 18 | public MixinAnvilSaveHandler(File p_i49566_1_, String p_i49566_2_, @Nullable MinecraftServer p_i49566_3_, DataFixer p_i49566_4_) { 19 | super(p_i49566_1_, p_i49566_2_, p_i49566_3_, p_i49566_4_); 20 | } 21 | 22 | @Overwrite 23 | @Override 24 | public IChunkLoader getChunkLoader(Dimension dimension) { 25 | File worldDirectory = getWorldDirectory(); 26 | int dimensionId = dimension.getType().getId(); 27 | if (dimensionId == 0) { 28 | return new AnvilChunkLoader(worldDirectory, dataFixer); 29 | } else { 30 | File dimensionFolder = new File(worldDirectory, "DIM" + dimensionId); 31 | dimensionFolder.mkdirs(); 32 | return new AnvilChunkLoader(dimensionFolder, dataFixer); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/client/MixinTileEntityRendererDispatcher.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook.client; 2 | 3 | import net.minecraft.client.renderer.tileentity.TileEntityRenderer; 4 | import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; 5 | import net.minecraft.tileentity.TileEntity; 6 | import org.dimdev.rift.listener.client.TileEntityRendererAdder; 7 | import org.dimdev.riftloader.RiftLoader; 8 | import org.spongepowered.asm.mixin.Final; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 14 | 15 | import java.util.Map; 16 | 17 | @Mixin(TileEntityRendererDispatcher.class) 18 | public class MixinTileEntityRendererDispatcher { 19 | @Shadow @Final private Map, TileEntityRenderer> renderers; 20 | 21 | @Inject(method = "", at = @At(value = "RETURN")) 22 | private void onRegisterTileEntityRenderDispatcher(CallbackInfo ci) { 23 | for (TileEntityRendererAdder tileEntityRendererAdder : RiftLoader.instance.getListeners(TileEntityRendererAdder.class)) { 24 | tileEntityRendererAdder.addTileEntityRenderers(renderers); 25 | } 26 | 27 | for (TileEntityRenderer renderer : renderers.values()) { 28 | renderer.setRendererDispatcher((TileEntityRendererDispatcher) (Object) this); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinWorldServer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.world.WorldServer; 4 | import net.minecraft.world.WorldType; 5 | import net.minecraft.world.dimension.Dimension; 6 | import net.minecraft.world.gen.IChunkGenSettings; 7 | import net.minecraft.world.gen.IChunkGenerator; 8 | import org.dimdev.rift.listener.ChunkGeneratorReplacer; 9 | import org.dimdev.riftloader.RiftLoader; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Redirect; 13 | 14 | @Mixin(WorldServer.class) 15 | public class MixinWorldServer { 16 | 17 | @SuppressWarnings("ConstantConditions") 18 | @Redirect(method = "createChunkProvider", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/dimension/Dimension;createChunkGenerator()Lnet/minecraft/world/gen/IChunkGenerator;")) 19 | protected IChunkGenerator onCreateChunkGenerator(Dimension dimension) { 20 | WorldServer world = (WorldServer) (Object) this; 21 | WorldType type = world.getWorldInfo().getGenerator(); 22 | IChunkGenerator generator = null; 23 | for(ChunkGeneratorReplacer adder : RiftLoader.instance.getListeners(ChunkGeneratorReplacer.class)) { 24 | IChunkGenerator value = adder.createChunkGenerator(world, type, dimension.getType().getId()); 25 | if(value != null) generator = value; 26 | } 27 | return generator != null ? generator : dimension.createChunkGenerator(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/riftloader/launch/RiftLoaderTweaker.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.riftloader.launch; 2 | 3 | import net.minecraft.launchwrapper.ITweaker; 4 | import net.minecraft.launchwrapper.Launch; 5 | import net.minecraft.launchwrapper.LaunchClassLoader; 6 | import org.spongepowered.asm.mixin.MixinEnvironment; 7 | 8 | import java.util.List; 9 | 10 | public abstract class RiftLoaderTweaker implements ITweaker { 11 | public List args; 12 | 13 | protected void addArg(String name, String value) { 14 | args.add(name); 15 | if (value != null) { 16 | args.add(value); 17 | } 18 | } 19 | 20 | @Override 21 | public void injectIntoClassLoader(LaunchClassLoader classLoader) { 22 | // Use the Launch classLoader to load the RiftLoader class. Otherwise identical 23 | // classes may not be equal, and 'instanceof' may return false when it should be true. 24 | try { 25 | Class clazz = Launch.classLoader.findClass("org.dimdev.riftloader.RiftLoader"); 26 | clazz.getMethod("load", boolean.class).invoke(clazz.getField("instance").get(null), isClient()); 27 | } catch (ReflectiveOperationException e) { 28 | throw new RuntimeException(e); 29 | } 30 | 31 | MixinEnvironment.getDefaultEnvironment().setSide(isClient() ? MixinEnvironment.Side.CLIENT : MixinEnvironment.Side.SERVER); 32 | } 33 | 34 | protected abstract boolean isClient(); 35 | 36 | @Override 37 | public String[] getLaunchArguments() { 38 | return args.toArray(new String[0]); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/resources/mixins.rift.hooks.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "minVersion": "0.7.7", 4 | "compatibilityLevel": "JAVA_8", 5 | "target": "@env(DEFAULT)", 6 | "package": "org.dimdev.rift.mixin.hook", 7 | "refmap": "mixins.rift.refmap.json", 8 | "mixins": [ 9 | "MixinBlock", 10 | "MixinItem", 11 | "MixinFluid", 12 | "MixinEnumConnectionState", 13 | "MixinEnumConnectionState$Handshaking", 14 | "MixinEnumConnectionState$Play", 15 | "MixinEnumConnectionState$Status", 16 | "MixinEnumConnectionState$Login", 17 | "MixinNetHandlerPlayServer", 18 | "MixinCommands", 19 | "MixinMinecraftServer", 20 | "MixinPotion", 21 | "MixinEnchantment", 22 | "MixinParticleType", 23 | "MixinSoundEvent", 24 | "MixinOverworldBiomeProvider", 25 | "MixinEntityType", 26 | "MixinTileEntityType", 27 | "MixinBootstrap", 28 | "MixinBiome", 29 | "MixinCPacketCustomPayload", 30 | "MixinEntityType$Builder", 31 | "MixinWorldServer", 32 | "MixinFurnace", 33 | "MixinAnvilSaveHandler", 34 | "MixinDimensionType", 35 | "MixinStructureIO", 36 | "MixinFeature", 37 | "MixinChunk", 38 | "MixinRecipeManager", 39 | "MixinRecipeSerializers", 40 | "MixinArgumentTypes", 41 | "MixinItemTool" 42 | ], 43 | "client": [ 44 | "client.MixinMinecraft", 45 | "client.MixinModelBakery", 46 | "client.MixinNetHandlerPlayClient", 47 | "client.MixinTileEntityRendererDispatcher", 48 | "client.MixinRenderManager", 49 | "client.MixinEntityPlayerSP", 50 | "client.MixinGameSettings", 51 | "client.MixinGuiIngame" 52 | ] 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/chocohead/rift/MappingBlob.java: -------------------------------------------------------------------------------- 1 | package com.chocohead.rift; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | import java.io.ObjectInputStream; 8 | import java.io.ObjectOutputStream; 9 | import java.io.Serializable; 10 | import java.util.Collections; 11 | import java.util.Map; 12 | import java.util.Map.Entry; 13 | import java.util.stream.Collectors; 14 | 15 | public class MappingBlob implements Serializable { 16 | private static final long serialVersionUID = 1807933665347803447L; 17 | 18 | public final Map mappings; 19 | public final Map nameBridge; 20 | 21 | public MappingBlob(Map mappings) { 22 | this.mappings = Collections.unmodifiableMap(mappings); 23 | nameBridge = Collections.unmodifiableMap(mappings.entrySet().parallelStream().collect(Collectors.toMap(mapping -> mapping.getValue().mcpName, Entry::getKey))); 24 | } 25 | 26 | public void write(File out) { 27 | try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(out))) { 28 | oos.writeObject(this); 29 | } catch (IOException e) { 30 | throw new RuntimeException("Error serialising mapping blob", e); 31 | } 32 | } 33 | 34 | public static MappingBlob read(File file) { 35 | try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) { 36 | return (MappingBlob) ois.readObject(); 37 | } catch (IOException e) { 38 | throw new RuntimeException("Error deserialising mapping blob", e); 39 | } catch (ClassNotFoundException e) { 40 | throw new IllegalStateException("Impossible?", e); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/main/java/org/dimdev/accesstransform/AccessTransformationSet.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.accesstransform; 2 | 3 | import java.util.HashMap; 4 | import java.util.HashSet; 5 | import java.util.Map; 6 | import java.util.Set; 7 | 8 | public class AccessTransformationSet { 9 | private final Map transformations = new HashMap<>(); 10 | private final Set affectedClasses = new HashSet<>(); 11 | 12 | public void addMimimumAccessLevel(ElementReference elementReference, AccessLevel accessLevel) { 13 | transformations.put(elementReference, AccessLevel.union(transformations.get(elementReference), accessLevel)); 14 | affectedClasses.add(elementReference.kind == ElementReference.Kind.CLASS ? elementReference.name : elementReference.owner); 15 | } 16 | 17 | public void addMinimumAccessLevel(String string) { 18 | string = string.trim(); 19 | if(string.isEmpty() || string.startsWith("#")) return; 20 | int indexOfFirstSpace = string.indexOf(' '); 21 | String accessLevel = string.substring(0, indexOfFirstSpace); 22 | String elementReference = string.substring(indexOfFirstSpace + 1); 23 | 24 | addMimimumAccessLevel(ElementReference.fromString(elementReference), AccessLevel.fromString(accessLevel)); 25 | } 26 | 27 | public AccessLevel getMinimumAccessLevel(ElementReference elementReference) { 28 | return transformations.get(elementReference); 29 | } 30 | 31 | public boolean isClassAffected(String name) { 32 | return affectedClasses.contains(name); 33 | } 34 | 35 | public boolean isEmpty() { 36 | return transformations.size() == 0; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/util/ItemTierImpl.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.util; 2 | 3 | import net.minecraft.item.IItemTier; 4 | import net.minecraft.item.crafting.Ingredient; 5 | import net.minecraft.util.LazyLoadBase; 6 | 7 | import java.util.function.Supplier; 8 | 9 | public class ItemTierImpl implements IItemTier { 10 | private final int harvestLevel; 11 | private final int maxUses; 12 | private final float efficiency; 13 | private final float attackDamage; 14 | private final int enchantability; 15 | private final LazyLoadBase ingredient; 16 | 17 | public ItemTierImpl(int harvestLevel, int maxUses, float efficiency, float attackDamage, int enchantability, Supplier ingredientSupplier) { 18 | this.harvestLevel = harvestLevel; 19 | this.maxUses = maxUses; 20 | this.efficiency = efficiency; 21 | this.attackDamage = attackDamage; 22 | this.enchantability = enchantability; 23 | this.ingredient = new LazyLoadBase<>(ingredientSupplier); 24 | } 25 | 26 | @Override 27 | public int getMaxUses() { 28 | return maxUses; 29 | } 30 | 31 | @Override 32 | public float getEfficiency() { 33 | return efficiency; 34 | } 35 | 36 | @Override 37 | public float getAttackDamage() { 38 | return attackDamage; 39 | } 40 | 41 | @Override 42 | public int getHarvestLevel() { 43 | return harvestLevel; 44 | } 45 | 46 | @Override 47 | public int getEnchantability() { 48 | return enchantability; 49 | } 50 | 51 | @Override 52 | public Ingredient getRepairMaterial() { 53 | return ingredient.getValue(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinBootstrap.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.init.Bootstrap; 4 | import org.dimdev.rift.listener.BootstrapListener; 5 | import org.dimdev.rift.listener.DispenserBehaviorAdder; 6 | import org.dimdev.rift.listener.MinecraftStartListener; 7 | import org.dimdev.riftloader.RiftLoader; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | import org.spongepowered.asm.mixin.injection.Inject; 11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 12 | 13 | @Mixin(Bootstrap.class) 14 | public class MixinBootstrap { 15 | @Inject(method = "registerDispenserBehaviors", at = @At("RETURN")) 16 | private static void onRegisterDispenserBehaviors(CallbackInfo ci) { 17 | for (DispenserBehaviorAdder dispenserBehaviorAdder : RiftLoader.instance.getListeners(DispenserBehaviorAdder.class)) { 18 | dispenserBehaviorAdder.registerDispenserBehaviors(); 19 | } 20 | } 21 | 22 | @Inject(method = "register", at = @At("HEAD")) 23 | private static void beforeBootstrapRegister(CallbackInfo ci) { 24 | for (MinecraftStartListener listener : RiftLoader.instance.getListeners(MinecraftStartListener.class)) { 25 | listener.onMinecraftStart(); 26 | } 27 | } 28 | 29 | @Inject(method = "register", at = @At(value = "INVOKE", target = "Lnet/minecraft/init/Bootstrap;redirectOutputToLog()V")) 30 | private static void afterBootstrapRegister(CallbackInfo ci) { 31 | for (BootstrapListener listener : RiftLoader.instance.getListeners(BootstrapListener.class)) { 32 | listener.afterVanillaBootstrap(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/core/client/MixinLayerArmorBase.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.core.client; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | import net.minecraft.client.renderer.entity.layers.LayerArmorBase; 7 | import net.minecraft.client.renderer.entity.model.ModelBase; 8 | import net.minecraft.util.ResourceLocation; 9 | 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.ModifyArg; 13 | 14 | @Mixin(LayerArmorBase.class) 15 | public class MixinLayerArmorBase { 16 | private static final Pattern TEXTURE_MASK = Pattern.compile("textures\\/models\\/armor\\/(.+)(_layer_\\d\\w*\\.png)"); 17 | 18 | @ModifyArg( 19 | method = "getArmorResource(Lnet/minecraft/item/ItemArmor;ZLjava/lang/String;)Lnet/minecraft/util/ResourceLocation;", 20 | at = @At( 21 | value = "INVOKE", 22 | target = "Ljava/util/Map;computeIfAbsent(Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object;", 23 | remap = false 24 | ), 25 | index = 0 26 | ) 27 | private Object getArmorTexture(Object old) { 28 | Matcher match = TEXTURE_MASK.matcher((String) old); 29 | if (!match.matches() || match.groupCount() != 2) { 30 | //Strange texture we can't resolve 31 | throw new IllegalArgumentException("Unexpected armor texture: " + old); 32 | } 33 | 34 | String name = match.group(1); 35 | String extra = match.group(2); 36 | ResourceLocation location = new ResourceLocation(name); 37 | 38 | return location.getNamespace() + ":textures/models/armor/" + location.getPath() + extra; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/client/MixinEntityPlayerSP.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook.client; 2 | 3 | import net.minecraft.client.entity.EntityPlayerSP; 4 | import net.minecraft.inventory.IInventory; 5 | import net.minecraft.world.IInteractionObject; 6 | import org.dimdev.rift.listener.client.GameGuiAdder; 7 | import org.dimdev.riftloader.RiftLoader; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | import org.spongepowered.asm.mixin.injection.Inject; 11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 12 | 13 | @Mixin(EntityPlayerSP.class) 14 | public class MixinEntityPlayerSP { 15 | @Inject(method = "displayGui", at = @At("HEAD"), cancellable = true) 16 | public void onDisplayGui(IInteractionObject interactionObject, CallbackInfo ci) { 17 | String id = interactionObject.getGuiID(); 18 | if (!id.startsWith("minecraft:")) { 19 | for (GameGuiAdder gameGuiAdder : RiftLoader.instance.getListeners(GameGuiAdder.class)) { 20 | gameGuiAdder.displayGui((EntityPlayerSP) (Object) this, id, interactionObject); 21 | } 22 | ci.cancel(); 23 | } 24 | } 25 | 26 | @Inject(method = "displayGUIChest", at = @At("HEAD"), cancellable = true) 27 | public void onDisplayContainerGui(IInventory inventory, CallbackInfo ci) { 28 | String id = inventory instanceof IInteractionObject ? ((IInteractionObject) inventory).getGuiID() : "minecraft:container"; 29 | if (!id.startsWith("minecraft:")) { 30 | for (GameGuiAdder gameGuiAdder : RiftLoader.instance.getListeners(GameGuiAdder.class)) { 31 | gameGuiAdder.displayContainerGui((EntityPlayerSP) (Object) this, id, inventory); 32 | } 33 | ci.cancel(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/riftloader/ModInfo.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.riftloader; 2 | 3 | import com.google.gson.*; 4 | import com.google.gson.annotations.SerializedName; 5 | 6 | import java.io.File; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public class ModInfo { 11 | public static Gson GSON = new GsonBuilder() 12 | .registerTypeAdapter(Listener.class, (JsonSerializer) (listener, type, context) -> { 13 | if (listener.priority == 0 && listener.side == Side.BOTH) { 14 | return new JsonPrimitive(listener.className); 15 | } 16 | 17 | return new Gson().toJsonTree(listener); 18 | }) 19 | .registerTypeAdapter(Listener.class, (JsonDeserializer) (json, type, context) -> { 20 | if (json.isJsonPrimitive() && ((JsonPrimitive) json).isString()) { 21 | return new Listener(json.getAsString()); 22 | } 23 | 24 | Listener listener = new Gson().fromJson(json, Listener.class); 25 | if (listener.className == null) throw new JsonSyntaxException("Listener with no class!"); 26 | //If the side isn't provided Gson helpfully returns null 27 | if (listener.side == null) listener.side = Side.BOTH; 28 | return listener; 29 | }) 30 | .create(); 31 | 32 | public static class Listener { 33 | @SerializedName("class") public String className; 34 | public int priority = 0; 35 | public Side side = Side.BOTH; 36 | 37 | public Listener(String className) { 38 | this.className = className; 39 | } 40 | } 41 | 42 | public File source; 43 | 44 | public String id; 45 | public String name; 46 | public List authors = new ArrayList<>(); 47 | public List listeners = new ArrayList<>(); 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/accesstransform/ElementReference.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.accesstransform; 2 | 3 | import java.util.Objects; 4 | 5 | public class ElementReference { 6 | public enum Kind { 7 | CLASS, 8 | METHOD, 9 | FIELD 10 | } 11 | 12 | public final Kind kind; 13 | public final String owner; 14 | public final String name; 15 | public final String desc; 16 | 17 | public ElementReference(Kind kind, String owner, String name, String desc) { 18 | this.kind = kind; 19 | this.owner = owner; 20 | this.name = name; 21 | this.desc = desc; 22 | } 23 | 24 | public static ElementReference fromString(String string) { 25 | String[] split = string.split(" "); 26 | 27 | switch (split[0]) { 28 | case "class": { 29 | return new ElementReference(Kind.CLASS, null, split[1], null); 30 | } 31 | 32 | case "method": { 33 | return new ElementReference(Kind.METHOD, split[1], split[2], split[3]); 34 | } 35 | 36 | case "field": { 37 | return new ElementReference(Kind.FIELD, split[1], split[2], split[3]); 38 | } 39 | 40 | default: { 41 | throw new RuntimeException("Unknown element type '" + split[0] + "'"); 42 | } 43 | } 44 | } 45 | 46 | @Override 47 | public boolean equals(Object obj) { 48 | return obj != null && 49 | obj.getClass() == ElementReference.class && 50 | ((ElementReference) obj).kind == kind && 51 | Objects.equals(((ElementReference) obj).owner, owner) && 52 | Objects.equals(((ElementReference) obj).name, name) && 53 | Objects.equals(((ElementReference) obj).desc, desc); 54 | } 55 | 56 | @Override 57 | public int hashCode() { 58 | return Objects.hash(kind, owner, name, desc); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/utils/NBTConstants.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.utils; 2 | 3 | import net.minecraft.nbt.NBTTagByte; 4 | import net.minecraft.nbt.NBTTagByteArray; 5 | import net.minecraft.nbt.NBTTagCompound; 6 | import net.minecraft.nbt.NBTTagDouble; 7 | import net.minecraft.nbt.NBTTagEnd; 8 | import net.minecraft.nbt.NBTTagFloat; 9 | import net.minecraft.nbt.NBTTagInt; 10 | import net.minecraft.nbt.NBTTagIntArray; 11 | import net.minecraft.nbt.NBTTagList; 12 | import net.minecraft.nbt.NBTTagLong; 13 | import net.minecraft.nbt.NBTTagLongArray; 14 | import net.minecraft.nbt.NBTTagShort; 15 | import net.minecraft.nbt.NBTTagString; 16 | 17 | public class NBTConstants { 18 | /** The ID for {@link NBTTagEnd} */ 19 | public static final int END = 0; 20 | /** The ID for {@link NBTTagByte} */ 21 | public static final int BYTE = 1; 22 | /** The ID for {@link NBTTagShort} */ 23 | public static final int SHORT = 2; 24 | /** The ID for {@link NBTTagInt} */ 25 | public static final int INT = 3; 26 | /** The ID for {@link NBTTagLong} */ 27 | public static final int LONG = 4; 28 | /** The ID for {@link NBTTagFloat} */ 29 | public static final int FLOAT = 5; 30 | /** The ID for {@link NBTTagDouble} */ 31 | public static final int DOUBLE = 6; 32 | /** The ID for {@link NBTTagByteArray} */ 33 | public static final int BYTE_ARRAY = 7; 34 | /** The ID for {@link NBTTagString} */ 35 | public static final int STRING = 8; 36 | /** The ID for {@link NBTTagList} */ 37 | public static final int LIST = 9; 38 | /** The ID for {@link NBTTagCompound} */ 39 | public static final int COMPOUND = 10; 40 | /** The ID for {@link NBTTagIntArray} */ 41 | public static final int INT_ARRAY = 11; 42 | /** The ID for {@link NBTTagLongArray} */ 43 | public static final int LONG_ARRAY = 12; 44 | /** Wildcard ID for any of {@link NBTTagByte}, {@link NBTTagShort}, {@link NBTTagInt}, {@link NBTTagLong}, {@link NBTTagFloat} or {@link NBTTagDouble} */ 45 | public static final int ANY_NUMERIC = 99; 46 | } -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/resources/ModPackFinder.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.resources; 2 | 3 | import net.minecraft.resources.IPackFinder; 4 | import net.minecraft.resources.ResourcePackInfo; 5 | import net.minecraft.resources.ResourcePackType; 6 | import net.minecraft.resources.data.PackMetadataSection; 7 | import org.dimdev.riftloader.ModInfo; 8 | import org.dimdev.riftloader.RiftLoader; 9 | 10 | import java.io.File; 11 | import java.io.IOException; 12 | import java.net.URL; 13 | import java.util.Map; 14 | 15 | public class ModPackFinder implements IPackFinder { 16 | private final ResourcePackType type; 17 | 18 | public ModPackFinder(ResourcePackType type) { 19 | this.type = type; 20 | } 21 | 22 | @Override 23 | public void addPackInfosToMap(Map nameToPackMap, ResourcePackInfo.IFactory packInfoFactory) { 24 | for (ModInfo mod : RiftLoader.instance.getMods()) { 25 | URL root = getRootUrl(mod); 26 | 27 | try (ModPack pack = new ModPack(mod.name != null ? mod.name : mod.id, root)) { 28 | PackMetadataSection meta = pack.getMetadata(PackMetadataSection.SERIALIZER); 29 | if (meta != null && !pack.getResourceNamespaces(type).isEmpty()) { 30 | nameToPackMap.put(mod.id, packInfoFactory.create(mod.id, type == ResourcePackType.CLIENT_RESOURCES, () -> pack, pack, meta, ResourcePackInfo.Priority.TOP)); 31 | } 32 | } catch (IOException ignored) {} 33 | } 34 | } 35 | 36 | public URL getRootUrl(ModInfo mod) { 37 | File source = mod.source; 38 | URL root; 39 | try { 40 | if (source.isFile()) { 41 | root = new URL("jar:" + source.toURI().toURL() + "!/"); 42 | } else { 43 | root = source.toURI().toURL(); 44 | } 45 | } catch (IOException e) { 46 | throw new RuntimeException(e); 47 | } 48 | return root; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/riftloader/OptifineLoader.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.riftloader; 2 | 3 | import net.minecraft.launchwrapper.ITweaker; 4 | import net.minecraft.launchwrapper.Launch; 5 | import net.minecraft.launchwrapper.LaunchClassLoader; 6 | 7 | import org.dimdev.rift.Rift.RiftTokens; 8 | import org.dimdev.riftloader.listener.InitializationListener; 9 | 10 | import org.spongepowered.asm.mixin.Mixins; 11 | 12 | import java.io.File; 13 | import java.util.List; 14 | 15 | public class OptifineLoader implements InitializationListener { 16 | public static final String OPTIFINE_TRANSFORMER = "optifine.OptiFineClassTransformer"; 17 | 18 | @Override 19 | public void onInitialization() { 20 | //noinspection unchecked 21 | ((List) Launch.blackboard.get("TweakClasses")).add("org.dimdev.riftloader.OptifineLoader$Tweaker"); 22 | Launch.classLoader.addClassLoaderExclusion("optifine."); 23 | RiftTokens.hasOptifine = true; 24 | Mixins.addConfiguration("mixins.rift.optifine.json"); 25 | } 26 | 27 | public static class Tweaker implements ITweaker { 28 | @Override 29 | public void acceptOptions(List args, File gameDir, File assetsDir, String profile) {} 30 | 31 | @Override 32 | public void injectIntoClassLoader(LaunchClassLoader classLoader) { 33 | if (RiftTokens.isObf) { 34 | //Use Optifine's ClassTransformer when we're running in a normal (obfuscated) environment 35 | classLoader.registerTransformer(OPTIFINE_TRANSFORMER); 36 | } else { 37 | //But if we're in a dev (deobfuscated) environment, we'll use our own 38 | classLoader.registerTransformer("org.dimdev.riftloader.OptifineDevTransformer"); 39 | } 40 | } 41 | 42 | @Override 43 | public String getLaunchTarget() { 44 | return null; 45 | } 46 | 47 | @Override 48 | public String[] getLaunchArguments() { 49 | return new String[0]; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/Rift.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift; 2 | 3 | import java.io.IOException; 4 | 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.dimdev.riftloader.listener.InitializationListener; 8 | import org.spongepowered.asm.launch.MixinBootstrap; 9 | import org.spongepowered.asm.mixin.MixinEnvironment; 10 | import org.spongepowered.asm.mixin.Mixins; 11 | import org.spongepowered.asm.mixin.extensibility.IEnvironmentTokenProvider; 12 | 13 | import net.minecraft.launchwrapper.Launch; 14 | 15 | public class Rift implements InitializationListener { 16 | public static final int DATAFIXER_VERSION = 1631; 17 | private static final Logger LOGGER = LogManager.getLogger(); 18 | 19 | @Override 20 | public void onInitialization() { 21 | LOGGER.info("Loading Rift!"); 22 | 23 | MixinBootstrap.init(); 24 | Mixins.addConfiguration("mixins.rift.core.json"); 25 | Mixins.addConfiguration("mixins.rift.hooks.json"); 26 | MixinEnvironment.getDefaultEnvironment().registerTokenProviderClass("org.dimdev.rift.Rift$RiftTokens"); 27 | } 28 | 29 | public static class RiftTokens implements IEnvironmentTokenProvider { 30 | /** Whether we are running with obfuscated Notch names or deobfuscated MCP names */ 31 | public static boolean isObf = isObf(); 32 | /** Whether Optifine is present and has probably been loaded */ 33 | public static boolean hasOptifine = false; 34 | 35 | private static boolean isObf() { 36 | try { 37 | return Launch.classLoader.getClassBytes("net.minecraft.world.World") == null; 38 | } catch (IOException e) { 39 | return true; //We probably are if we can't find World 40 | } 41 | } 42 | 43 | @Override 44 | public int getPriority() { 45 | return DEFAULT_PRIORITY; 46 | } 47 | 48 | @Override 49 | public Integer getToken(String token, MixinEnvironment env) { 50 | switch (token) { 51 | case "OBF": 52 | return isObf ? 1 : 0; 53 | 54 | case "OPTIFINE": 55 | return hasOptifine ? 2 : 0; 56 | 57 | default: 58 | return null; 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinNetHandlerPlayServer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.entity.player.EntityPlayerMP; 4 | import net.minecraft.network.NetHandlerPlayServer; 5 | import net.minecraft.network.NetworkManager; 6 | import net.minecraft.network.PacketBuffer; 7 | import net.minecraft.network.play.client.CPacketCustomPayload; 8 | import net.minecraft.server.MinecraftServer; 9 | import net.minecraft.util.ResourceLocation; 10 | import org.dimdev.rift.injectedmethods.RiftCPacketCustomPayload; 11 | import org.dimdev.rift.network.Message; 12 | import org.dimdev.rift.network.ServerMessageContext; 13 | import org.dimdev.riftloader.RiftLoader; 14 | import org.spongepowered.asm.mixin.Final; 15 | import org.spongepowered.asm.mixin.Mixin; 16 | import org.spongepowered.asm.mixin.Shadow; 17 | import org.spongepowered.asm.mixin.injection.At; 18 | import org.spongepowered.asm.mixin.injection.Inject; 19 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 20 | 21 | @Mixin(NetHandlerPlayServer.class) 22 | public class MixinNetHandlerPlayServer { 23 | @Shadow @Final private MinecraftServer server; 24 | @Shadow public EntityPlayerMP player; 25 | @Shadow @Final public NetworkManager netManager; 26 | 27 | @Inject(method = "processCustomPayload", at = @At("HEAD"), cancellable = true) 28 | private void handleModCustomPayload(CPacketCustomPayload packet, CallbackInfo ci) { 29 | if (Message.REGISTRY.isEmpty()) return; 30 | 31 | ResourceLocation channelName = ((RiftCPacketCustomPayload) packet).getChannelName(); 32 | Class messageClass = Message.REGISTRY.get(channelName); 33 | if (messageClass != null) { 34 | PacketBuffer data = ((RiftCPacketCustomPayload) packet).getData(); 35 | 36 | try { 37 | Message message = RiftLoader.instance.newInstance(messageClass); 38 | message.read(data); 39 | message.process(new ServerMessageContext(server, player, netManager)); 40 | } catch (ReflectiveOperationException e) { 41 | throw new RuntimeException("Error creating " + messageClass, e); 42 | } 43 | ci.cancel(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/util/ArmorMaterialImpl.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.util; 2 | 3 | import net.minecraft.inventory.EntityEquipmentSlot; 4 | import net.minecraft.item.ArmorMaterial; 5 | import net.minecraft.item.IArmorMaterial; 6 | import net.minecraft.item.crafting.Ingredient; 7 | import net.minecraft.util.LazyLoadBase; 8 | import net.minecraft.util.SoundEvent; 9 | 10 | import java.util.function.Supplier; 11 | 12 | public class ArmorMaterialImpl implements IArmorMaterial { 13 | private final String name; 14 | private final int maxDamageFactor; 15 | private final int[] damageReductionAmountArray; 16 | private final int enchantability; 17 | private final SoundEvent soundEvent; 18 | private final float toughness; 19 | private final LazyLoadBase ingredient; 20 | 21 | public ArmorMaterialImpl(String name, int maxDamageFactor, int[] damageReductionAmountArray, int enchantability, SoundEvent soundEvent, float toughness, Supplier ingredientSupplier) { 22 | this.name = name; 23 | this.maxDamageFactor = maxDamageFactor; 24 | this.damageReductionAmountArray = damageReductionAmountArray; 25 | this.enchantability = enchantability; 26 | this.soundEvent = soundEvent; 27 | this.toughness = toughness; 28 | this.ingredient = new LazyLoadBase<>(ingredientSupplier); 29 | } 30 | 31 | @Override 32 | public int getDurability(EntityEquipmentSlot slot) { 33 | return ArmorMaterial.MAX_DAMAGE_ARRAY[slot.getIndex()] * maxDamageFactor; 34 | } 35 | 36 | @Override 37 | public int getDamageReductionAmount(EntityEquipmentSlot slot) { 38 | return damageReductionAmountArray[slot.getIndex()]; 39 | } 40 | 41 | @Override 42 | public int getEnchantability() { 43 | return enchantability; 44 | } 45 | 46 | @Override 47 | public SoundEvent getSoundEvent() { 48 | return soundEvent; 49 | } 50 | 51 | @Override 52 | public Ingredient getRepairMaterial() { 53 | return ingredient.getValue(); 54 | } 55 | 56 | @Override 57 | public String getName() { 58 | return name; 59 | } 60 | 61 | @Override 62 | public float getToughness() { 63 | return toughness; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/core/MixinVanillaPack.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.core; 2 | 3 | import net.minecraft.resources.ResourcePackType; 4 | import net.minecraft.resources.VanillaPack; 5 | import net.minecraft.util.ResourceLocation; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.Overwrite; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | 10 | import javax.annotation.Nullable; 11 | import java.io.IOException; 12 | import java.io.InputStream; 13 | import java.net.URL; 14 | import java.nio.file.Files; 15 | import java.nio.file.Path; 16 | 17 | @Mixin(VanillaPack.class) 18 | public class MixinVanillaPack { 19 | @Shadow public static Path basePath; 20 | 21 | /** 22 | * @reason Give priority to resources in the Minecraft jar to avoid them 23 | * from being overwritten by mods. 24 | */ 25 | @Nullable 26 | @Overwrite(constraints = "OPTIFINE(0-1)") 27 | protected InputStream getInputStreamVanilla(ResourcePackType type, ResourceLocation location) { 28 | String pathString = type.getDirectoryName() + "/" + location.getNamespace() + "/" + location.getPath(); 29 | 30 | if (basePath != null) { 31 | Path path = basePath.resolve(pathString); 32 | if (Files.exists(path)) { 33 | try { 34 | return Files.newInputStream(path); 35 | } catch (IOException ignored) {} 36 | } 37 | } 38 | 39 | try { 40 | URL rootMarker = VanillaPack.class.getResource("/" + type.getDirectoryName() + "/.mcassetsroot"); 41 | String root = rootMarker.toString().substring(0, rootMarker.toString().length() - ".mcassetsroot".length()); 42 | String path = location.getNamespace() + "/" + location.getPath(); 43 | return new URL(root + path).openStream(); 44 | } catch (IOException ignored) {} 45 | 46 | // Realms and Optifine just add resources to the classpath. If no resources were 47 | // found in the Minecraft jar, fall back to looking on the classpath. Duplicates 48 | // will be handled by the classpath order. 49 | return VanillaPack.class.getResourceAsStream("/" + type.getDirectoryName() + "/" + location.getNamespace() + "/" + location.getPath()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinEntityType.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import com.mojang.datafixers.DataFixUtils; 4 | import com.mojang.datafixers.types.Type; 5 | import net.minecraft.entity.Entity; 6 | import net.minecraft.entity.EntityType; 7 | import net.minecraft.util.datafix.DataFixesManager; 8 | import net.minecraft.util.datafix.TypeReferences; 9 | import net.minecraft.world.World; 10 | import org.apache.logging.log4j.LogManager; 11 | import org.apache.logging.log4j.Logger; 12 | import org.dimdev.rift.Rift; 13 | import org.dimdev.rift.listener.EntityTypeAdder; 14 | import org.dimdev.riftloader.RiftLoader; 15 | import org.spongepowered.asm.mixin.Final; 16 | import org.spongepowered.asm.mixin.Mixin; 17 | import org.spongepowered.asm.mixin.Overwrite; 18 | import org.spongepowered.asm.mixin.Shadow; 19 | 20 | import java.util.function.Function; 21 | 22 | @Mixin(EntityType.class) 23 | public abstract class MixinEntityType { 24 | static { 25 | for (EntityTypeAdder entityTypeAdder : RiftLoader.instance.getListeners(EntityTypeAdder.class)) { 26 | entityTypeAdder.registerEntityTypes(); 27 | } 28 | } 29 | 30 | @Mixin(EntityType.Builder.class) 31 | public abstract static class Builder { 32 | @Shadow private boolean serializable; 33 | 34 | @Shadow @Final private Class entityClass; 35 | @Shadow @Final private Function factory; 36 | @Shadow private boolean summonable; 37 | private static final Logger LOGGER = LogManager.getLogger(); 38 | 39 | @Overwrite 40 | public EntityType build(String id) { 41 | Type dataFixerType = null; 42 | 43 | if (serializable) { 44 | try { 45 | dataFixerType = DataFixesManager.getDataFixer().getSchema(DataFixUtils.makeKey(Rift.DATAFIXER_VERSION)).getChoiceType(TypeReferences.ENTITY_TYPE, id); 46 | } catch (IllegalStateException | IllegalArgumentException ignored) { 47 | LOGGER.debug("No data fixer registered for entity {}", id); 48 | } 49 | } 50 | 51 | return new EntityType<>(entityClass, factory, serializable, summonable, dataFixerType); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinTileEntityType.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import com.mojang.datafixers.DataFixUtils; 4 | import com.mojang.datafixers.types.Type; 5 | import net.minecraft.tileentity.TileEntity; 6 | import net.minecraft.tileentity.TileEntityType; 7 | import net.minecraft.util.ResourceLocation; 8 | import net.minecraft.util.datafix.DataFixesManager; 9 | import net.minecraft.util.datafix.TypeReferences; 10 | import net.minecraft.util.registry.IRegistry; 11 | import org.apache.logging.log4j.Logger; 12 | import org.dimdev.rift.Rift; 13 | import org.dimdev.rift.listener.TileEntityTypeAdder; 14 | import org.dimdev.riftloader.RiftLoader; 15 | import org.spongepowered.asm.mixin.Final; 16 | import org.spongepowered.asm.mixin.Mixin; 17 | import org.spongepowered.asm.mixin.Overwrite; 18 | import org.spongepowered.asm.mixin.Shadow; 19 | import org.spongepowered.asm.mixin.injection.At; 20 | import org.spongepowered.asm.mixin.injection.Inject; 21 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 22 | 23 | @Mixin(TileEntityType.class) 24 | public abstract class MixinTileEntityType { 25 | @Shadow @Final private static Logger LOGGER; 26 | 27 | @Overwrite 28 | public static TileEntityType register(String id, TileEntityType.Builder builder) { 29 | Type dataFixerType = null; 30 | 31 | try { 32 | //Schema#getChoiceType can throw an IAE that vanilla won't catch, so we catch that too 33 | dataFixerType = DataFixesManager.getDataFixer().getSchema(DataFixUtils.makeKey(Rift.DATAFIXER_VERSION)).getChoiceType(TypeReferences.BLOCK_ENTITY, id); 34 | } catch (IllegalStateException | IllegalArgumentException e) { 35 | LOGGER.debug("No data fixer registered for block entity {}", id); 36 | } 37 | 38 | TileEntityType tileEntityType = builder.build(dataFixerType); 39 | IRegistry.BLOCK_ENTITY_TYPE.put(new ResourceLocation(id), tileEntityType); 40 | return tileEntityType; 41 | } 42 | 43 | @Inject(method = "", at = @At("RETURN")) 44 | private static void onRegisterTileEntityTypes(CallbackInfo ci) { 45 | for (TileEntityTypeAdder entityTypeAdder : RiftLoader.instance.getListeners(TileEntityTypeAdder.class)) { 46 | entityTypeAdder.registerTileEntityTypes(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/debug/java/org/dimdev/testmod/ExplosionCommand.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.testmod; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.arguments.ArgumentType; 5 | import com.mojang.brigadier.arguments.BoolArgumentType; 6 | import com.mojang.brigadier.arguments.IntegerArgumentType; 7 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 8 | import com.mojang.brigadier.builder.RequiredArgumentBuilder; 9 | import net.minecraft.command.CommandSource; 10 | import net.minecraft.entity.Entity; 11 | 12 | public class ExplosionCommand { 13 | public static void register(CommandDispatcher dispatcher) { 14 | LiteralArgumentBuilder builder = literalArgument("explosion") 15 | .executes(context -> { 16 | Entity entity = context.getSource().getEntity(); 17 | entity.world.newExplosion(null, entity.posX, entity.posY, entity.posZ, 1, true, true); 18 | return 0; 19 | }) 20 | .then(requiredArgument("strength", IntegerArgumentType.integer(0)) 21 | .executes(context -> { 22 | Entity entity = context.getSource().getEntity(); 23 | entity.world.newExplosion(null, entity.posX, entity.posY, entity.posZ, context.getArgument("strength", Integer.class), true, true); 24 | return 0; 25 | }) 26 | .then(requiredArgument("causesFire", BoolArgumentType.bool()) 27 | .executes(context -> { 28 | Entity entity = context.getSource().getEntity(); 29 | entity.world.newExplosion(null, entity.posX, entity.posY, entity.posZ, context.getArgument("strength", Integer.class), context.getArgument("causesFire", Boolean.class), true); 30 | return 0; 31 | }))); 32 | dispatcher.register(builder); 33 | } 34 | 35 | private static LiteralArgumentBuilder literalArgument(String name) { 36 | return LiteralArgumentBuilder.literal(name); 37 | } 38 | 39 | private static RequiredArgumentBuilder requiredArgument(String name, ArgumentType type) { 40 | return RequiredArgumentBuilder.argument(name, type); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/optifine/client/MixinBlockFluidRenderer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.optifine.client; 2 | 3 | import net.minecraft.client.renderer.BlockFluidRenderer; 4 | import net.minecraft.client.renderer.BufferBuilder; 5 | import net.minecraft.client.renderer.texture.MissingTextureSprite; 6 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 7 | import net.minecraft.fluid.IFluidState; 8 | import net.minecraft.util.math.BlockPos; 9 | import net.minecraft.world.IWorldReader; 10 | 11 | import org.objectweb.asm.Opcodes; 12 | 13 | import org.spongepowered.asm.mixin.Mixin; 14 | import org.spongepowered.asm.mixin.injection.At; 15 | import org.spongepowered.asm.mixin.injection.Redirect; 16 | 17 | import org.dimdev.rift.injectedmethods.RiftFluid; 18 | 19 | @Mixin(BlockFluidRenderer.class) 20 | public class MixinBlockFluidRenderer { 21 | @Redirect(at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/BlockFluidRenderer;atlasSpritesWater:[Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;", opcode = Opcodes.GETFIELD), method = "render(Lnet/minecraft/world/IWorldReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/client/renderer/BufferBuilder;Lnet/minecraft/fluid/IFluidState;)Z", constraints = "OPTIFINE(1+)") 22 | public TextureAtlasSprite[] getWaterFluidTextures(BlockFluidRenderer me, IWorldReader world, BlockPos pos, BufferBuilder buffer, IFluidState state) { 23 | if (state.getFluid() instanceof RiftFluid) { 24 | RiftFluid fluid = (RiftFluid) state.getFluid(); 25 | return new TextureAtlasSprite[] {fluid.getStillTexture(), fluid.getFlowingTexture()}; 26 | } else { 27 | return new TextureAtlasSprite[] {MissingTextureSprite.getSprite(), MissingTextureSprite.getSprite()}; 28 | } 29 | } 30 | 31 | @Redirect(at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/BlockFluidRenderer;atlasSpritesLava:[Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;", opcode = Opcodes.GETFIELD), method = "render(Lnet/minecraft/world/IWorldReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/client/renderer/BufferBuilder;Lnet/minecraft/fluid/IFluidState;)Z", constraints = "OPTIFINE(1+)") 32 | public TextureAtlasSprite[] getLavaFluidTextures(BlockFluidRenderer me, IWorldReader world, BlockPos pos, BufferBuilder buffer, IFluidState state) { 33 | if (state.getFluid() instanceof RiftFluid) { 34 | RiftFluid fluid = (RiftFluid) state.getFluid(); 35 | return new TextureAtlasSprite[] {fluid.getStillTexture(), fluid.getFlowingTexture()}; 36 | } else { 37 | return new TextureAtlasSprite[] {MissingTextureSprite.getSprite(), MissingTextureSprite.getSprite()}; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/main/java/org/dimdev/utils/ReflectionUtils.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.utils; 2 | 3 | import java.lang.invoke.MethodHandle; 4 | import java.lang.invoke.MethodHandles; 5 | import java.lang.reflect.Constructor; 6 | import java.lang.reflect.Field; 7 | import java.lang.reflect.Method; 8 | import java.net.URL; 9 | import java.net.URLClassLoader; 10 | import java.util.Arrays; 11 | 12 | public class ReflectionUtils { 13 | private static final MethodHandle addURLHandle; 14 | 15 | static { 16 | try { 17 | Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); 18 | method.setAccessible(true); 19 | addURLHandle = MethodHandles.lookup().unreflect(method); 20 | } catch (ReflectiveOperationException e) { 21 | throw new AssertionError(e); 22 | } 23 | } 24 | 25 | public static T makeEnumInstance(Class enumClass, Object... constructorArgs) { 26 | try { 27 | Constructor constructor = enumClass.getDeclaredConstructors()[0]; 28 | constructor.setAccessible(true); 29 | 30 | //noinspection unchecked 31 | return (T) MethodHandles.lookup().unreflectConstructor(constructor).invokeWithArguments(constructorArgs); 32 | } catch (Throwable t) { 33 | throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t); 34 | } 35 | } 36 | 37 | public static Field findField(Class target, Class fieldType) throws NoSuchFieldException { 38 | for (Field field : target.getDeclaredFields()) { 39 | if (field.getType() == fieldType) { 40 | field.setAccessible(true); 41 | return field; 42 | } 43 | } 44 | 45 | throw new NoSuchFieldException("Cannot find field in " + target + '#' + fieldType); 46 | } 47 | 48 | public static Method findMethod(Class target, Class returnType, Class... params) throws NoSuchMethodException { 49 | for (Method method : target.getDeclaredMethods()) { 50 | if (method.getReturnType() == returnType && Arrays.equals(method.getParameterTypes(), params)) { 51 | method.setAccessible(true); 52 | return method; 53 | } 54 | } 55 | 56 | throw new NoSuchMethodException("Cannot find method in " + target + '(' + Arrays.toString(params) + ") " + returnType); 57 | } 58 | 59 | public static void addURLToClasspath(URL url) { 60 | try { 61 | addURLHandle.invoke(ClassLoader.getSystemClassLoader(), url); 62 | } catch (Throwable t) { 63 | throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/resources/access_transformations.at: -------------------------------------------------------------------------------- 1 | public method bcs a (Lpc;Lbcs;)V # net.minecraft.block.Block/register 2 | public method bcs$c a (Lbhr;)Lbcs$c; # net.minecraft.block.Block$Properties/sound 3 | public method bcs$c a (I)Lbcs$c; # net.minecraft.block.Block$Properties/lightValue 4 | public method bcs$c b ()Lbcs$c; # net.minecraft.block.Block$Properties/zeroHardnessAndResistance 5 | public method bcs$c c ()Lbcs$c; # net.minecraft.block.Block$Properties/needsRandomTick 6 | public method bcs$c d ()Lbcs$c; # net.minecraft.block.Block$Properties/variableOpacity 7 | 8 | public method ata b (Lbcs;)V # net.minecraft.item.Item/register 9 | public method ata a (Lbcs;Lary;)V # net.minecraft.item.Item/register 10 | public method ata a (Lpc;Lata;)V # net.minecraft.item.Item/register 11 | public method ata a (Lbcs;Lata;)V # net.minecraft.item.Item/register 12 | public method ata a (Larj;)V # net.minecraft.item.Item/register 13 | 14 | public method byv a (Lpc;Lbyv;)V # net.minecraft.fluid.Fluid/register 15 | public method bfu (Lbyu;Lbcs$c;)V # net.minecraft.block.BlockFlowingFluid/ 16 | 17 | public method bod (ILjava/lang/String;Ljava/lang/String;Ljava/util/function/Supplier;)V # net.minecraft.world.dimension.DimensionType/ 18 | public method bod a (Ljava/lang/String;Lbod;)Lbod; # net.minecraft.world.dimension.DimensionType/register 19 | 20 | public method ayu a (ILjava/lang/String;Layu;)V # net.minecraft.world.biome.Biome/register 21 | 22 | public method fl (Lpc;ZLfk$a;)V # net.minecraft.particles.ParticleType/ 23 | public method fl a (Ljava/lang/String;Z)V # net.minecraft.particles.ParticleType/register 24 | public method fl a (Ljava/lang/String;ZLfk$a;)V # net.minecraft.particles.ParticleType/register 25 | public method fn (Lpc;Z)V # net.minecraft.particles.BasicParticleType/ 26 | 27 | public method awe a (Ljava/lang/String;Lawe;)V # net.minecraft.enchantment.Enchantment/func_210770_a 28 | public method aej a (ILjava/lang/String;Laej;)V # net.minecraft.potion.Potion/func_210759_a 29 | 30 | public method wi a (Ljava/lang/String;)V # net.minecraft.util.SoundEvent/register 31 | 32 | public method ayg (ILjava/lang/String;I)V # net.minecraft.world.WorldType/ 33 | public method ayg (ILjava/lang/String;)V # net.minecraft.world.WorldType/ 34 | public method ayg (ILjava/lang/String;Ljava/lang/String;I)V # net.minecraft.world.WorldType/ 35 | public class bna # net.minecraft.world.gen.IChunkGeneratorFactory 36 | public class bnd # net.minecraft.world.chunk.ChunkStatus 37 | public method bwy b (Ljava/lang/Class;Ljava/lang/String;)V # net.minecraft.world.gen.feature.structure.StructureIO/registerStructure 38 | 39 | public field ard g [I # net.minecraft.item.ArmorMaterial/MAX_DAMAGE_ARRAY 40 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinEnumConnectionState.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.network.EnumConnectionState; 4 | import net.minecraft.network.EnumPacketDirection; 5 | import net.minecraft.network.Packet; 6 | import org.dimdev.rift.listener.PacketAdder; 7 | import org.dimdev.riftloader.RiftLoader; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | import org.spongepowered.asm.mixin.injection.At; 11 | import org.spongepowered.asm.mixin.injection.Inject; 12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 13 | 14 | @Mixin(EnumConnectionState.class) 15 | public abstract class MixinEnumConnectionState { 16 | @Shadow protected abstract EnumConnectionState registerPacket(EnumPacketDirection direction, Class> packetClass); 17 | 18 | @Mixin(targets = "net/minecraft/network/EnumConnectionState$1") 19 | public abstract static class Handshaking extends MixinEnumConnectionState { 20 | @Inject(method = "", at = @At("RETURN")) 21 | private void registerModPackets(CallbackInfo ci) { 22 | for (PacketAdder packetAdder : RiftLoader.instance.getListeners(PacketAdder.class)) { 23 | packetAdder.registerHandshakingPackets(this::registerPacket); 24 | } 25 | } 26 | } 27 | 28 | @Mixin(targets = "net/minecraft/network/EnumConnectionState$2") 29 | public abstract static class Play extends MixinEnumConnectionState { 30 | @Inject(method = "", at = @At("RETURN")) 31 | private void registerModPackets(CallbackInfo ci) { 32 | for (PacketAdder packetAdder : RiftLoader.instance.getListeners(PacketAdder.class)) { 33 | packetAdder.registerPlayPackets(this::registerPacket); 34 | } 35 | } 36 | } 37 | 38 | @Mixin(targets = "net/minecraft/network/EnumConnectionState$3") 39 | public abstract static class Status extends MixinEnumConnectionState { 40 | @Inject(method = "", at = @At("RETURN")) 41 | private void registerModPackets(CallbackInfo ci) { 42 | for (PacketAdder packetAdder : RiftLoader.instance.getListeners(PacketAdder.class)) { 43 | packetAdder.registerStatusPackets(this::registerPacket); 44 | } 45 | } 46 | } 47 | 48 | @Mixin(targets = "net/minecraft/network/EnumConnectionState$4") 49 | public abstract static class Login extends MixinEnumConnectionState { 50 | @Inject(method = "", at = @At("RETURN")) 51 | private void registerModPackets(CallbackInfo ci) { 52 | for (PacketAdder packetAdder : RiftLoader.instance.getListeners(PacketAdder.class)) { 53 | packetAdder.registerLoginPackets(this::registerPacket); 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/network/ClientMessageContext.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.network; 2 | 3 | import com.mojang.authlib.GameProfile; 4 | import com.mojang.brigadier.CommandDispatcher; 5 | import net.minecraft.client.Minecraft; 6 | import net.minecraft.client.multiplayer.ClientAdvancementManager; 7 | import net.minecraft.client.multiplayer.ClientSuggestionProvider; 8 | import net.minecraft.client.util.NBTQueryManager; 9 | import net.minecraft.command.ISuggestionProvider; 10 | import net.minecraft.item.crafting.RecipeManager; 11 | import net.minecraft.network.NetworkManager; 12 | import net.minecraft.tags.NetworkTagManager; 13 | 14 | public class ClientMessageContext implements MessageContext { 15 | private final Minecraft client; 16 | private final GameProfile profile; 17 | private final NetworkManager networkManager; 18 | private final RecipeManager recipeManager; 19 | private final ClientAdvancementManager advancementManager; 20 | private final CommandDispatcher commandDispatcher; 21 | private final ClientSuggestionProvider clientSuggestionProvider; 22 | private final NetworkTagManager networkTagManager; 23 | private final NBTQueryManager nbtQueryManager; 24 | 25 | public ClientMessageContext( 26 | Minecraft client, 27 | GameProfile profile, 28 | NetworkManager networkManager, 29 | RecipeManager recipeManager, 30 | ClientAdvancementManager advancementManager, 31 | CommandDispatcher commandDispatcher, 32 | ClientSuggestionProvider clientSuggestionProvider, 33 | NetworkTagManager networkTagManager, 34 | NBTQueryManager nbtQueryManager 35 | ) { 36 | this.client = client; 37 | this.profile = profile; 38 | this.networkManager = networkManager; 39 | this.recipeManager = recipeManager; 40 | this.advancementManager = advancementManager; 41 | this.commandDispatcher = commandDispatcher; 42 | this.clientSuggestionProvider = clientSuggestionProvider; 43 | this.networkTagManager = networkTagManager; 44 | this.nbtQueryManager = nbtQueryManager; 45 | } 46 | 47 | public Minecraft getClient() { 48 | return client; 49 | } 50 | 51 | public GameProfile getProfile() { 52 | return profile; 53 | } 54 | 55 | @Override 56 | public NetworkManager getNetworkManager() { 57 | return networkManager; 58 | } 59 | 60 | public RecipeManager getRecipeManager() { 61 | return recipeManager; 62 | } 63 | 64 | public ClientAdvancementManager getAdvancementManager() { 65 | return advancementManager; 66 | } 67 | 68 | public CommandDispatcher getCommandDispatcher() { 69 | return commandDispatcher; 70 | } 71 | 72 | public ClientSuggestionProvider getSuggestionProvider() { 73 | return clientSuggestionProvider; 74 | } 75 | 76 | public NetworkTagManager getNetworkTagManager() { 77 | return networkTagManager; 78 | } 79 | 80 | public NBTQueryManager getNbtQueryManager() { 81 | return nbtQueryManager; 82 | } 83 | 84 | @Override 85 | public void reply(Message message) { 86 | message.sendToServer(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/com/chocohead/rift/RemappingClassAdapter.java: -------------------------------------------------------------------------------- 1 | package com.chocohead.rift; 2 | 3 | import java.util.Map; 4 | import java.util.Set; 5 | 6 | import org.objectweb.asm.ClassVisitor; 7 | import org.objectweb.asm.Handle; 8 | import org.objectweb.asm.MethodVisitor; 9 | import org.objectweb.asm.Opcodes; 10 | import org.objectweb.asm.Type; 11 | import org.objectweb.asm.commons.ClassRemapper; 12 | import org.objectweb.asm.commons.MethodRemapper; 13 | import org.objectweb.asm.commons.Remapper; 14 | 15 | import com.google.common.collect.ImmutableSet; 16 | 17 | public class RemappingClassAdapter extends ClassRemapper { 18 | private static class BlobRemapper extends Remapper { 19 | private final Map mappings; 20 | 21 | public BlobRemapper(MappingBlob mapping) { 22 | mappings = mapping.mappings; 23 | } 24 | 25 | @Override 26 | public String map(String name) { 27 | ClassMapping map = mappings.get(name); 28 | return map != null ? map.mcpName : name; 29 | } 30 | 31 | @Override 32 | public String mapFieldName(String owner, String name, String descriptor) { 33 | ClassMapping map = mappings.get(owner); 34 | if (map == null) return name; 35 | 36 | return map.fields.getOrDefault(name + ";;" + descriptor, name); 37 | } 38 | 39 | @Override 40 | public String mapMethodName(String owner, String name, String descriptor) { 41 | ClassMapping map = mappings.get(owner); 42 | if (map == null) return name; 43 | 44 | return map.methods.getOrDefault(name + descriptor, name); 45 | } 46 | } 47 | 48 | public RemappingClassAdapter(ClassVisitor cv, MappingBlob mapping) { 49 | super(cv, new BlobRemapper(mapping)); 50 | } 51 | 52 | @Override 53 | protected MethodVisitor createMethodRemapper(MethodVisitor mv) { 54 | return new AsmMethodRemapper(mv, remapper); 55 | } 56 | 57 | private static class AsmMethodRemapper extends MethodRemapper { 58 | private static final Set META_FACTORIES = ImmutableSet.of( 59 | new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", 60 | "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;" 61 | + "Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;", 62 | false), 63 | new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "altMetafactory", 64 | "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)" 65 | + "Ljava/lang/invoke/CallSite;", 66 | false) 67 | ); 68 | 69 | public AsmMethodRemapper(MethodVisitor mv, Remapper remapper) { 70 | super(mv, remapper); 71 | } 72 | 73 | @Override 74 | public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { 75 | if (META_FACTORIES.contains(bsm)) { 76 | String owner = Type.getReturnType(desc).getInternalName(); 77 | String ownerDesc = ((Type) bsmArgs[0]).getDescriptor(); 78 | 79 | name = remapper.mapMethodName(owner, name, ownerDesc); 80 | } 81 | 82 | super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/client/MixinMinecraft.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook.client; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.audio.MusicTicker; 5 | import net.minecraft.client.resources.ResourcePackInfoClient; 6 | import net.minecraft.profiler.Profiler; 7 | import net.minecraft.resources.IPackFinder; 8 | import net.minecraft.resources.ResourcePackList; 9 | import org.dimdev.rift.listener.client.KeybindHandler; 10 | import org.dimdev.rift.listener.client.AmbientMusicTypeProvider; 11 | import org.dimdev.rift.listener.client.ClientTickable; 12 | import org.dimdev.rift.listener.ResourcePackFinderAdder; 13 | import org.dimdev.riftloader.RiftLoader; 14 | import org.spongepowered.asm.mixin.Final; 15 | import org.spongepowered.asm.mixin.Mixin; 16 | import org.spongepowered.asm.mixin.Shadow; 17 | import org.spongepowered.asm.mixin.injection.At; 18 | import org.spongepowered.asm.mixin.injection.Inject; 19 | import org.spongepowered.asm.mixin.injection.Redirect; 20 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 21 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 22 | 23 | @Mixin(Minecraft.class) 24 | public class MixinMinecraft { 25 | @Shadow @Final private ResourcePackList resourcePackRepository; 26 | @Shadow @Final public Profiler profiler; 27 | 28 | @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/resources/ResourcePackList;addPackFinder(Lnet/minecraft/resources/IPackFinder;)V", ordinal = 1)) 29 | private void onAddResourcePacks(ResourcePackList resourcePackList, IPackFinder minecraftPackFinder) { 30 | resourcePackList.addPackFinder(minecraftPackFinder); 31 | 32 | for (ResourcePackFinderAdder resourcePackFinderAdder : RiftLoader.instance.getListeners(ResourcePackFinderAdder.class)) { 33 | for (IPackFinder packFinder : resourcePackFinderAdder.getResourcePackFinders()) { 34 | resourcePackRepository.addPackFinder(packFinder); 35 | } 36 | } 37 | } 38 | 39 | @Inject(method = "runTick", at = @At("RETURN")) 40 | private void onTick(CallbackInfo ci) { 41 | profiler.startSection("mods"); 42 | for (ClientTickable tickable : RiftLoader.instance.getListeners(ClientTickable.class)) { 43 | profiler.startSection(() -> tickable.getClass().getCanonicalName().replace('.', '/')); 44 | tickable.clientTick((Minecraft) (Object) this); 45 | profiler.endSection(); 46 | } 47 | profiler.endSection(); 48 | } 49 | 50 | @Inject(method = "getAmbientMusicType", at = @At(value = "INVOKE"), cancellable = true) 51 | private void getMusicType(CallbackInfoReturnable cir) { 52 | for (AmbientMusicTypeProvider ambientMusicTypeProvider : RiftLoader.instance.getListeners(AmbientMusicTypeProvider.class)) { 53 | MusicTicker.MusicType type = ambientMusicTypeProvider.getAmbientMusicType((Minecraft) (Object) this); 54 | 55 | if(type != null) { 56 | cir.setReturnValue(type); 57 | cir.cancel(); 58 | return; 59 | } 60 | } 61 | } 62 | 63 | @Inject(method = "processKeyBinds", at = @At("HEAD")) 64 | public void onProcessKeyBinds(CallbackInfo ci) { 65 | for (KeybindHandler keybindHandler : RiftLoader.instance.getListeners(KeybindHandler.class)) { 66 | keybindHandler.processKeybinds(); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/debug/java/org/dimdev/testmod/TestDimension.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.testmod; 2 | 3 | import java.util.Random; 4 | 5 | import net.minecraft.init.Blocks; 6 | import net.minecraft.util.math.BlockPos; 7 | import net.minecraft.util.math.ChunkPos; 8 | import net.minecraft.util.math.MathHelper; 9 | import net.minecraft.util.math.Vec3d; 10 | import net.minecraft.world.biome.provider.BiomeProviderType; 11 | import net.minecraft.world.dimension.Dimension; 12 | import net.minecraft.world.dimension.DimensionType; 13 | import net.minecraft.world.dimension.EndDimension; 14 | import net.minecraft.world.gen.ChunkGeneratorType; 15 | import net.minecraft.world.gen.EndGenSettings; 16 | import net.minecraft.world.gen.IChunkGenerator; 17 | 18 | /** Loose clone of {@link EndDimension} */ 19 | public class TestDimension extends Dimension { 20 | private static DimensionType type; 21 | 22 | @Override 23 | protected void init() { 24 | hasSkyLight = false; 25 | } 26 | 27 | @Override 28 | public IChunkGenerator createChunkGenerator() { 29 | EndGenSettings endGenerator = ChunkGeneratorType.FLOATING_ISLANDS.createSettings(); 30 | 31 | endGenerator.setDefautBlock(Blocks.WHITE_CONCRETE.getDefaultState()); 32 | endGenerator.setDefaultFluid(Blocks.AIR.getDefaultState()); 33 | endGenerator.setSpawnPos(getSpawnCoordinate()); 34 | 35 | return ChunkGeneratorType.FLOATING_ISLANDS.create(world, BiomeProviderType.THE_END.create(BiomeProviderType.THE_END.createSettings().setSeed(world.getSeed())), endGenerator); 36 | } 37 | 38 | @Override 39 | public BlockPos getSpawnCoordinate() { 40 | return EndDimension.SPAWN; 41 | } 42 | 43 | @Override 44 | public BlockPos findSpawn(ChunkPos chunk, boolean checkValid) { 45 | Random random = new Random(world.getSeed()); 46 | BlockPos pos = new BlockPos(chunk.getXStart() + random.nextInt(15), 0, chunk.getZEnd() + random.nextInt(15)); 47 | return world.getGroundAboveSeaLevel(pos).getMaterial().blocksMovement() ? pos : null; 48 | } 49 | 50 | @Override 51 | public BlockPos findSpawn(int x, int z, boolean checkValid) { 52 | return findSpawn(new ChunkPos(x >> 4, z >> 4), checkValid); 53 | } 54 | 55 | @Override 56 | public boolean isSurfaceWorld() { 57 | return false; 58 | } 59 | 60 | @Override 61 | public float calculateCelestialAngle(long worldTime, float partialTicks) { 62 | return 0F; 63 | } 64 | 65 | @Override 66 | public float[] calcSunriseSunsetColors(float celestialAngle, float partialTicks) { 67 | return null; 68 | } 69 | 70 | @Override 71 | public boolean doesXZShowFog(int x, int z) { 72 | return false; 73 | } 74 | 75 | @Override 76 | public Vec3d getFogColor(float celestialAngle, float partialTicks) { 77 | float sun = MathHelper.cos(celestialAngle * ((float)Math.PI * 2F)) * 2F + 0.5F; 78 | sun = MathHelper.clamp(sun, 0F, 1F); 79 | 80 | float r = 0.627451F; 81 | float g = 0.5019608F; 82 | float b = 0.627451F; 83 | r = r * (sun * 0.0F + 0.15F); 84 | g = g * (sun * 0.0F + 0.15F); 85 | b = b * (sun * 0.0F + 0.15F); 86 | 87 | return new Vec3d(r, g, b); 88 | } 89 | 90 | @Override 91 | public boolean canRespawnHere() { 92 | return false; 93 | } 94 | 95 | @Override 96 | public float getCloudHeight() { 97 | return 8F; 98 | } 99 | 100 | static void giveType(DimensionType type) { 101 | TestDimension.type = type; 102 | } 103 | 104 | @Override 105 | public DimensionType getType() { 106 | if (type == null) throw new IllegalStateException("Null type?"); 107 | return type; 108 | } 109 | } -------------------------------------------------------------------------------- /src/main/java/org/dimdev/accesstransform/AccessTransformer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.accesstransform; 2 | 3 | 4 | import org.objectweb.asm.ClassReader; 5 | import org.objectweb.asm.ClassWriter; 6 | import org.objectweb.asm.Opcodes; 7 | import org.objectweb.asm.tree.ClassNode; 8 | import org.objectweb.asm.tree.FieldNode; 9 | import org.objectweb.asm.tree.MethodNode; 10 | 11 | public class AccessTransformer { 12 | private final AccessTransformationSet transformations; 13 | 14 | public AccessTransformer(AccessTransformationSet transformations) { 15 | this.transformations = transformations; 16 | } 17 | 18 | public byte[] transformClass(String name, byte[] bytes) { 19 | if (bytes == null || !transformations.isClassAffected(name)) { 20 | return bytes; 21 | } 22 | 23 | ClassNode clazz = new ClassNode(); 24 | ClassReader reader = new ClassReader(bytes); 25 | reader.accept(clazz, 0); 26 | 27 | // Transform class access level 28 | clazz.access = getNewAccessLevel(new ElementReference(ElementReference.Kind.CLASS, null, name, null), clazz.access); 29 | 30 | for (FieldNode field : clazz.fields) { 31 | field.access = getNewAccessLevel(new ElementReference(ElementReference.Kind.FIELD, name, field.name, field.desc), field.access); 32 | } 33 | 34 | for (MethodNode method : clazz.methods) { 35 | method.access = getNewAccessLevel(new ElementReference(ElementReference.Kind.METHOD, name, method.name, method.desc), method.access); 36 | } 37 | 38 | ClassWriter writer = new ClassWriter(0); 39 | clazz.accept(writer); 40 | return writer.toByteArray(); 41 | } 42 | 43 | private int getNewAccessLevel(ElementReference elementReference, int access) { 44 | AccessLevel minimumAccessLevel = transformations.getMinimumAccessLevel(elementReference); 45 | if (minimumAccessLevel == null) { 46 | return access; 47 | } 48 | 49 | AccessLevel.Visibility visibility; 50 | if ((access & Opcodes.ACC_PUBLIC) != 0) { 51 | visibility = AccessLevel.Visibility.PUBLIC; 52 | access &= ~Opcodes.ACC_PUBLIC; 53 | } else if ((access & Opcodes.ACC_PROTECTED) != 0) { 54 | visibility = AccessLevel.Visibility.PROTECTED; 55 | access &= ~Opcodes.ACC_PROTECTED; 56 | } else if ((access & Opcodes.ACC_PRIVATE) != 0) { 57 | visibility = AccessLevel.Visibility.PRIVATE; 58 | access &= ~Opcodes.ACC_PRIVATE; 59 | } else { 60 | visibility = AccessLevel.Visibility.DEFAULT; 61 | } 62 | boolean isFinal = (access & Opcodes.ACC_FINAL) != 0; 63 | 64 | AccessLevel newAccessLevel = AccessLevel.union(minimumAccessLevel, new AccessLevel(visibility, isFinal)); 65 | if (newAccessLevel == null) { 66 | return access; 67 | } 68 | 69 | if (isFinal && !newAccessLevel.isFinal) { 70 | access &= ~Opcodes.ACC_FINAL; 71 | } 72 | 73 | switch (newAccessLevel.visibility) { 74 | case PUBLIC: { 75 | return access | Opcodes.ACC_PUBLIC; 76 | } 77 | 78 | case PROTECTED: { 79 | return access | Opcodes.ACC_PROTECTED; 80 | } 81 | 82 | case DEFAULT: { 83 | return access; 84 | } 85 | 86 | case PRIVATE: { 87 | return access | Opcodes.ACC_PRIVATE; 88 | } 89 | 90 | default: { 91 | throw new RuntimeException("Unknown visibility level '" + newAccessLevel.visibility + "'"); 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/optifine/MixinVanillaPack.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.optifine; 2 | 3 | import net.minecraft.resources.ResourcePackType; 4 | import net.minecraft.resources.VanillaPack; 5 | import net.minecraft.util.ResourceLocation; 6 | 7 | import org.dimdev.riftloader.OptifineLoader; 8 | import org.dimdev.utils.ReflectionUtils; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Overwrite; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | 13 | import javax.annotation.Nullable; 14 | 15 | import java.io.ByteArrayInputStream; 16 | import java.io.IOException; 17 | import java.io.InputStream; 18 | import java.lang.invoke.MethodHandle; 19 | import java.lang.invoke.MethodHandles; 20 | import java.lang.reflect.Field; 21 | import java.lang.reflect.Method; 22 | import java.net.URL; 23 | import java.nio.file.Files; 24 | import java.nio.file.Path; 25 | import java.util.function.Function; 26 | 27 | @Mixin(VanillaPack.class) 28 | public class MixinVanillaPack { 29 | @Shadow public static Path basePath; 30 | 31 | /** 32 | * @reason Give priority to resources in the Minecraft jar to avoid them 33 | * from being overwritten by mods. 34 | */ 35 | @Nullable 36 | @Overwrite(constraints = "OPTIFINE(1+)") 37 | protected InputStream getInputStreamVanilla(ResourcePackType type, ResourceLocation location) { 38 | String pathString = type.getDirectoryName() + "/" + location.getNamespace() + "/" + location.getPath(); 39 | 40 | InputStream in = optifineResourceFisher.apply(pathString); 41 | if (in != null) return in; 42 | 43 | if (basePath != null) { 44 | Path path = basePath.resolve(pathString); 45 | if (Files.exists(path)) { 46 | try { 47 | return Files.newInputStream(path); 48 | } catch (IOException ignored) {} 49 | } 50 | } 51 | 52 | try { 53 | URL rootMarker = VanillaPack.class.getResource("/" + type.getDirectoryName() + "/.mcassetsroot"); 54 | String root = rootMarker.toString().substring(0, rootMarker.toString().length() - ".mcassetsroot".length()); 55 | String path = location.getNamespace() + "/" + location.getPath(); 56 | return new URL(root + path).openStream(); 57 | } catch (IOException ignored) { 58 | return VanillaPack.class.getResourceAsStream("/" + pathString); 59 | } 60 | } 61 | 62 | private static final Function optifineResourceFisher; 63 | static { 64 | //Ironically Optifine does all this via reflection too, so we're actually no slower than how it otherwise works 65 | try { 66 | //Fish for the type 67 | Class transformer = Class.forName(OptifineLoader.OPTIFINE_TRANSFORMER); 68 | //Then the instance field Optifine helpfully hangs onto 69 | Field instanceField = ReflectionUtils.findField(transformer, transformer); 70 | Object instance = instanceField.get(null); 71 | if (instance == null) throw new IllegalStateException("Transformer hasn't loaded yet?"); 72 | //Now fish for the method 73 | Method method = transformer.getDeclaredMethod("getOptiFineResource", String.class); 74 | MethodHandle handle = MethodHandles.lookup().unreflect(method); 75 | optifineResourceFisher = path -> { 76 | try { 77 | byte[] resource = (byte[]) handle.invoke(instance, path); 78 | return resource != null ? new ByteArrayInputStream(resource) : null; 79 | } catch (Throwable t) { 80 | throw new RuntimeException("Error getting resource from Optifine", t); 81 | } 82 | }; 83 | } catch (ReflectiveOperationException e) { 84 | throw new RuntimeException("Unable to get Optifine resource method", e); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /src/debug/java/org/dimdev/testmod/ChangeDimensionCommand.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.testmod; 2 | 3 | import java.lang.invoke.MethodHandles; 4 | import java.lang.reflect.Method; 5 | import java.util.Arrays; 6 | import java.util.Collection; 7 | import java.util.Collections; 8 | 9 | import org.dimdev.utils.ReflectionUtils; 10 | 11 | import com.mojang.brigadier.CommandDispatcher; 12 | import com.mojang.brigadier.arguments.ArgumentType; 13 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 14 | import com.mojang.brigadier.builder.RequiredArgumentBuilder; 15 | import com.mojang.brigadier.context.CommandContext; 16 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 17 | 18 | import net.minecraft.command.CommandSource; 19 | import net.minecraft.command.arguments.DimensionArgument; 20 | import net.minecraft.command.arguments.ILocationArgument; 21 | import net.minecraft.command.arguments.LocationInput; 22 | import net.minecraft.command.arguments.LocationPart; 23 | import net.minecraft.command.arguments.Vec3Argument; 24 | import net.minecraft.command.impl.TeleportCommand; 25 | import net.minecraft.entity.Entity; 26 | import net.minecraft.util.math.BlockPos; 27 | import net.minecraft.world.WorldServer; 28 | import net.minecraft.world.dimension.DimensionType; 29 | 30 | public class ChangeDimensionCommand { 31 | public static void register(CommandDispatcher dispatcher) { 32 | LiteralArgumentBuilder builder = literalArgument("changedimension") 33 | .then(requiredArgument("dimension", DimensionArgument.getDimension()) 34 | .executes(context -> { 35 | WorldServer world = context.getSource().getServer().getWorld(DimensionArgument.func_212592_a(context, "dimension")); 36 | 37 | BlockPos pos = world.getSpawnCoordinate(); 38 | if (pos == null) pos = world.getSpawnPoint(); 39 | 40 | return teleport(context, new LocationInput(new LocationPart(false, pos.getX()), new LocationPart(false, pos.getY()), new LocationPart(false, pos.getZ()))); 41 | })) 42 | .then(requiredArgument("dimension", DimensionArgument.getDimension()) 43 | .then(requiredArgument("location", Vec3Argument.vec3()) 44 | .executes(context -> teleport(context, Vec3Argument.getLocation(context, "location")) 45 | ))); 46 | dispatcher.register(builder); 47 | } 48 | 49 | private static LiteralArgumentBuilder literalArgument(String name) { 50 | return LiteralArgumentBuilder.literal(name); 51 | } 52 | 53 | private static RequiredArgumentBuilder requiredArgument(String name, ArgumentType type) { 54 | return RequiredArgumentBuilder.argument(name, type); 55 | } 56 | 57 | static int teleport(CommandContext context, ILocationArgument location) throws CommandSyntaxException { 58 | Entity entity = context.getSource().assertIsEntity(); 59 | DimensionType type = DimensionArgument.func_212592_a(context, "dimension"); 60 | 61 | try { 62 | Class facing = Arrays.stream(TeleportCommand.class.getDeclaredClasses()).filter(Class::isMemberClass).findFirst().get(); //Grab TeleportCommand.Facing, only need it to pass null in 63 | Method m = ReflectionUtils.findMethod(TeleportCommand.class, int.class, CommandSource.class, Collection.class, WorldServer.class, ILocationArgument.class, ILocationArgument.class, facing); 64 | MethodHandles.lookup().unreflect(m).invokeWithArguments(context.getSource(), Collections.singleton(entity), context.getSource().getServer().getWorld(type), location, LocationInput.current(), null); 65 | } catch (Throwable t) { 66 | throw new RuntimeException("Error teleporting " + entity + " to " + type, t); 67 | } 68 | 69 | return 1; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/MixinMinecraftServer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook; 2 | 3 | import net.minecraft.profiler.Profiler; 4 | import net.minecraft.resources.IPackFinder; 5 | import net.minecraft.resources.ResourcePackInfo; 6 | import net.minecraft.resources.ResourcePackList; 7 | import net.minecraft.server.MinecraftServer; 8 | import net.minecraft.world.GameType; 9 | import net.minecraft.world.ServerWorldEventHandler; 10 | import net.minecraft.world.WorldServer; 11 | import net.minecraft.world.WorldServerMulti; 12 | import net.minecraft.world.WorldSettings; 13 | import net.minecraft.world.dimension.DimensionType; 14 | import net.minecraft.world.storage.ISaveHandler; 15 | import net.minecraft.world.storage.WorldInfo; 16 | import net.minecraft.world.storage.WorldSavedDataStorage; 17 | 18 | import org.dimdev.rift.listener.DataPackFinderAdder; 19 | import org.dimdev.rift.listener.ServerTickable; 20 | import org.dimdev.riftloader.RiftLoader; 21 | 22 | import org.spongepowered.asm.mixin.Final; 23 | import org.spongepowered.asm.mixin.Mixin; 24 | import org.spongepowered.asm.mixin.Shadow; 25 | import org.spongepowered.asm.mixin.injection.At; 26 | import org.spongepowered.asm.mixin.injection.Inject; 27 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 28 | 29 | import java.io.File; 30 | import java.util.Map; 31 | 32 | @Mixin(MinecraftServer.class) 33 | public abstract class MixinMinecraftServer { 34 | @Shadow @Final private ResourcePackList resourcePacks; 35 | @Shadow @Final public Profiler profiler; 36 | 37 | @Shadow @Final public Map worlds; 38 | @Shadow public abstract WorldServer getWorld(DimensionType dimension); 39 | @Shadow public abstract GameType getGameType(); 40 | @Shadow public abstract boolean isSinglePlayer(); 41 | 42 | @Inject(method = "loadDataPacks", at = @At(value = "INVOKE", target = "Lnet/minecraft/resources/ResourcePackList;reloadPacksFromFinders()V")) 43 | private void afterAddVanillaPackFinder(File serverDirectory, WorldInfo worldInfo, CallbackInfo ci) { 44 | for (DataPackFinderAdder resourcePackFinderAdder : RiftLoader.instance.getListeners(DataPackFinderAdder.class)) { 45 | for (IPackFinder packFinder : resourcePackFinderAdder.getDataPackFinders()) { 46 | resourcePacks.addPackFinder(packFinder); 47 | } 48 | } 49 | } 50 | 51 | @Inject(method = "tick", at = @At(value = "RETURN")) 52 | private void onTick(CallbackInfo ci) { 53 | profiler.startSection("mods"); 54 | for (ServerTickable tickable : RiftLoader.instance.getListeners(ServerTickable.class)) { 55 | profiler.startSection(() -> tickable.getClass().getCanonicalName().replace('.', '/')); 56 | tickable.serverTick((MinecraftServer) (Object) this); 57 | profiler.endSection(); 58 | } 59 | profiler.endSection(); 60 | } 61 | 62 | @Inject(method = "func_212369_a", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/management/PlayerList;func_212504_a(Lnet/minecraft/world/WorldServer;)V")) 63 | private void onWorldLoad(ISaveHandler saveHandler, WorldSavedDataStorage savedDataStorage, WorldInfo info, WorldSettings settings, CallbackInfo ci) { 64 | WorldServer overworld = getWorld(DimensionType.OVERWORLD); 65 | 66 | for (DimensionType type : DimensionType.func_212681_b()) { 67 | //Skip around existing types (the Overworld, Nether and End) 68 | if (!worlds.containsKey(type)) { 69 | WorldServerMulti world = new WorldServerMulti((MinecraftServer) (Object) this, saveHandler, type, overworld, profiler); 70 | world.func_212251_i__(); 71 | 72 | worlds.put(type, world); 73 | 74 | world.addEventListener(new ServerWorldEventHandler((MinecraftServer) (Object) this, world)); 75 | if (!isSinglePlayer()) { 76 | world.getWorldInfo().setGameType(getGameType()); 77 | } 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/network/Message.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.network; 2 | 3 | import io.netty.buffer.Unpooled; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.client.entity.EntityPlayerSP; 6 | import net.minecraft.entity.player.EntityPlayer; 7 | import net.minecraft.entity.player.EntityPlayerMP; 8 | import net.minecraft.network.EnumPacketDirection; 9 | import net.minecraft.network.INetHandler; 10 | import net.minecraft.network.Packet; 11 | import net.minecraft.network.PacketBuffer; 12 | import net.minecraft.network.play.client.CPacketCustomPayload; 13 | import net.minecraft.network.play.server.SPacketCustomPayload; 14 | import net.minecraft.server.MinecraftServer; 15 | import net.minecraft.util.ResourceLocation; 16 | import net.minecraft.util.registry.IRegistry; 17 | import net.minecraft.util.registry.RegistryNamespaced; 18 | import net.minecraft.world.WorldServer; 19 | import org.dimdev.rift.util.RegistryUtil; 20 | 21 | import java.util.function.Predicate; 22 | 23 | public abstract class Message { 24 | public static final IRegistry> REGISTRY = RegistryUtil.createRegistry(new ResourceLocation("rift", "message"), new RegistryNamespaced<>()); 25 | 26 | public abstract void write(PacketBuffer buffer); 27 | 28 | public abstract void read(PacketBuffer buffer); 29 | 30 | public void process(ClientMessageContext context) { 31 | throw new UnsupportedOperationException("Packet " + getClass() + " can't be processed on client."); 32 | } 33 | 34 | public void process(ServerMessageContext context) { 35 | throw new UnsupportedOperationException("Packet " + getClass() + " can't be processed on server."); 36 | } 37 | 38 | public final Packet toPacket(EnumPacketDirection direction) { 39 | ResourceLocation id = Message.REGISTRY.getKey(getClass()); 40 | if (id == null) { 41 | throw new IllegalArgumentException("Message was not registered: " + this); 42 | } 43 | 44 | PacketBuffer buffer = new PacketBuffer(Unpooled.buffer()); 45 | write(buffer); 46 | switch (direction) { 47 | case CLIENTBOUND: 48 | return new SPacketCustomPayload(id, buffer); 49 | case SERVERBOUND: 50 | return new CPacketCustomPayload(id, buffer); 51 | default: 52 | throw new AssertionError("unreachable"); 53 | } 54 | } 55 | 56 | public final void send(EntityPlayer player) { 57 | if (player instanceof EntityPlayerMP) { 58 | ((EntityPlayerMP) player).connection.getNetworkManager().sendPacket(toPacket(EnumPacketDirection.CLIENTBOUND)); 59 | } else if (player instanceof EntityPlayerSP) { 60 | ((EntityPlayerSP) player).connection.getNetworkManager().sendPacket(toPacket(EnumPacketDirection.SERVERBOUND)); 61 | } else { 62 | throw new IllegalArgumentException("Only supported for EntityPlayerMP and EntityPlayerSP, but got " + player.getClass()); 63 | } 64 | } 65 | 66 | public final void sendToAll(MinecraftServer server) { 67 | for (EntityPlayerMP player : server.getPlayerList().getPlayers()) { 68 | send(player); 69 | } 70 | } 71 | 72 | public final void sendToAll(MinecraftServer server, Predicate filter) { 73 | for (EntityPlayerMP player : server.getPlayerList().getPlayers()) { 74 | if (filter.test(player)) { 75 | send(player); 76 | } 77 | } 78 | } 79 | 80 | public final void sendToAll(WorldServer world, Predicate filter) { 81 | for (EntityPlayerMP player : world.getPlayers(EntityPlayerMP.class, filter)) { 82 | send(player); 83 | } 84 | } 85 | 86 | public final void sendToAll(WorldServer world) { 87 | for (EntityPlayerMP player : world.getPlayers(EntityPlayerMP.class, player -> true)) { 88 | send(player); 89 | } 90 | } 91 | 92 | public void sendToServer() { 93 | Minecraft.getInstance().player.connection.sendPacket(toPacket(EnumPacketDirection.SERVERBOUND)); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/mixin/hook/client/MixinNetHandlerPlayClient.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.mixin.hook.client; 2 | 3 | import com.mojang.authlib.GameProfile; 4 | import com.mojang.brigadier.CommandDispatcher; 5 | import net.minecraft.client.Minecraft; 6 | import net.minecraft.client.multiplayer.ClientAdvancementManager; 7 | import net.minecraft.client.multiplayer.ClientSuggestionProvider; 8 | import net.minecraft.client.multiplayer.WorldClient; 9 | import net.minecraft.client.network.NetHandlerPlayClient; 10 | import net.minecraft.client.util.NBTQueryManager; 11 | import net.minecraft.command.ISuggestionProvider; 12 | import net.minecraft.item.crafting.RecipeManager; 13 | import net.minecraft.network.NetworkManager; 14 | import net.minecraft.network.PacketBuffer; 15 | import net.minecraft.network.play.server.SPacketCustomPayload; 16 | import net.minecraft.network.play.server.SPacketUpdateTileEntity; 17 | import net.minecraft.tags.NetworkTagManager; 18 | import net.minecraft.tileentity.TileEntity; 19 | import net.minecraft.tileentity.TileEntityType; 20 | import net.minecraft.util.ResourceLocation; 21 | import org.dimdev.rift.network.ClientMessageContext; 22 | import org.dimdev.rift.network.Message; 23 | import org.dimdev.riftloader.RiftLoader; 24 | import org.spongepowered.asm.mixin.Final; 25 | import org.spongepowered.asm.mixin.Mixin; 26 | import org.spongepowered.asm.mixin.Shadow; 27 | import org.spongepowered.asm.mixin.injection.At; 28 | import org.spongepowered.asm.mixin.injection.Inject; 29 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 30 | 31 | @Mixin(NetHandlerPlayClient.class) 32 | public class MixinNetHandlerPlayClient { 33 | @Shadow private WorldClient world; 34 | 35 | @Shadow @Final private GameProfile profile; 36 | @Shadow private Minecraft client; 37 | @Shadow @Final private RecipeManager recipeManager; 38 | @Shadow @Final private ClientAdvancementManager advancementManager; 39 | @Shadow @Final private NetworkManager netManager; 40 | @Shadow private CommandDispatcher commandDispatcher; 41 | @Shadow @Final private ClientSuggestionProvider clientSuggestionProvider; 42 | @Shadow private NetworkTagManager networkTagManager; 43 | @Shadow private NBTQueryManager nbtQueryManager; 44 | 45 | @Inject(method = "handleCustomPayload", at = @At("HEAD"), cancellable = true) 46 | private void handleModCustomPayload(SPacketCustomPayload packet, CallbackInfo ci) { 47 | if (Message.REGISTRY.isEmpty()) return; 48 | 49 | ResourceLocation channelName = packet.getChannelName(); 50 | Class messageClass = Message.REGISTRY.get(channelName); 51 | if (messageClass != null) { 52 | PacketBuffer data = packet.getBufferData(); 53 | 54 | try { 55 | Message message = RiftLoader.instance.newInstance(messageClass); 56 | message.read(data); 57 | message.process(new ClientMessageContext( 58 | client, 59 | profile, 60 | netManager, 61 | recipeManager, 62 | advancementManager, 63 | commandDispatcher, 64 | clientSuggestionProvider, 65 | networkTagManager, 66 | nbtQueryManager 67 | )); 68 | } catch (ReflectiveOperationException e) { 69 | throw new RuntimeException("Error creating " + messageClass, e); 70 | } 71 | ci.cancel(); 72 | } 73 | } 74 | 75 | @Inject(method = "handleUpdateTileEntity", at = @At("RETURN")) 76 | private void handleUpdateModTileEntity(SPacketUpdateTileEntity packet, CallbackInfo ci) { 77 | TileEntity tileEntity = world.getTileEntity(packet.getPos()); 78 | if (tileEntity == null || packet.getNbtCompound() == null || !packet.getNbtCompound().contains("id", 8)) { 79 | return; 80 | } 81 | 82 | ResourceLocation tileEntityId = TileEntityType.getId(tileEntity.getType()); 83 | ResourceLocation packetId = new ResourceLocation(packet.getNbtCompound().getString("id")); 84 | if (!packetId.getNamespace().equals("minecraft") && packetId.equals(tileEntityId)) { 85 | tileEntity.read(packet.getNbtCompound()); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/riftloader/OptifineDevTransformer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.riftloader; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.net.MalformedURLException; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import java.util.jar.JarFile; 9 | import java.util.zip.ZipEntry; 10 | import java.util.zip.ZipFile; 11 | 12 | import org.objectweb.asm.ClassReader; 13 | import org.objectweb.asm.ClassWriter; 14 | import org.objectweb.asm.tree.ClassNode; 15 | 16 | import com.google.common.io.ByteStreams; 17 | 18 | import net.minecraft.launchwrapper.IClassTransformer; 19 | import net.minecraft.launchwrapper.Launch; 20 | 21 | import org.dimdev.utils.ReflectionUtils; 22 | 23 | import com.chocohead.rift.ClassMapping; 24 | import com.chocohead.rift.MappingBlob; 25 | import com.chocohead.rift.RemappingClassAdapter; 26 | 27 | public class OptifineDevTransformer implements IClassTransformer { 28 | /** Vanilla (obfuscated) jar, used by Optifine to apply its patches */ 29 | private final ZipFile vanilla; 30 | /** The Optifine transformer, we wrap this so we can interfere with what it does */ 31 | private final IClassTransformer transformer; 32 | /** The current mappings we apply on top of what Optifine does */ 33 | private final MappingBlob mappings; 34 | 35 | public OptifineDevTransformer() { 36 | File vanilla = new File(System.getProperty("vanilla-jar", 37 | System.getProperty("user.home") + "/.gradle/caches/minecraft/net/minecraft/minecraft/1.13.2/minecraft-1.13.2.jar")); 38 | //First check to see if the location we've ended up at is actually valid 39 | if (!vanilla.exists() || !vanilla.isFile()) { 40 | throw new IllegalStateException("Unable to find vanilla jar at " + vanilla); 41 | } 42 | //Now try to open it so we can pull classes out 43 | try { 44 | this.vanilla = new JarFile(vanilla); 45 | } catch (IOException e) { 46 | throw new RuntimeException("Unable to open vanilla jar at " + vanilla, e); 47 | } 48 | 49 | //We need the actual transformer to save a whole lot more reflecting into Optifine 50 | try { 51 | transformer = (IClassTransformer) Launch.classLoader.findClass(OptifineLoader.OPTIFINE_TRANSFORMER).newInstance(); 52 | } catch (ReflectiveOperationException e) { 53 | throw new RuntimeException("Error creating Optifine class transformer", e); 54 | } 55 | 56 | //Fishing for mapping versions is guess work at best, we'll rely on being given what should be right 57 | File mappings = new File(System.getProperty("mappings", "NONE-PROVIDED")); 58 | if (!mappings.exists() || !mappings.isFile()) { 59 | throw new IllegalStateException("Unable to find mappings at " + vanilla); 60 | } 61 | MappingBlob temp = MappingBlob.read(mappings); 62 | Map map = new HashMap<>(temp.mappings); 63 | //Optifine extends a couple of vanilla classes which means mappings get missed 64 | addOptifineExtension(map, "net/optifine/render/AabbFrame", "cea"); 65 | addOptifineExtension(map, "net/optifine/override/ChunkCacheOF", "aye"); 66 | addOptifineExtension(map, "net/optifine/override/PlayerControllerOF", "crf"); 67 | addOptifineExtension(map, "net/optifine/gui/GuiScreenOF", "ckd"); 68 | 69 | this.mappings = new MappingBlob(map); 70 | 71 | try { 72 | ReflectionUtils.addURLToClasspath(vanilla.toURI().toURL()); 73 | } catch (MalformedURLException e) { 74 | throw new RuntimeException("Error putting vanilla jar on classpath", e); 75 | } 76 | } 77 | 78 | private static void addOptifineExtension(Map map, String optiClass, String notchClass) { 79 | ClassMapping aabbFrame = new ClassMapping(optiClass, optiClass); 80 | aabbFrame.methods.putAll(map.get(notchClass).methods); 81 | aabbFrame.fields.putAll(map.get(notchClass).fields); 82 | map.put(optiClass, aabbFrame); 83 | } 84 | 85 | @Override 86 | public byte[] transform(String name, String transformedName, byte[] basicClass) { 87 | String notch = mappings.nameBridge.get(name.replace('.', '/')); 88 | 89 | if (notch != null) { 90 | ZipEntry entry = vanilla.getEntry(notch + ".class"); 91 | 92 | if (entry != null) { 93 | try { 94 | byte[] vanillaClass = ByteStreams.toByteArray(vanilla.getInputStream(entry)); 95 | byte[] optiClass = transformer.transform(notch, name, vanillaClass); 96 | 97 | if (optiClass != vanillaClass) { 98 | //System.out.println("Transforming vanilla class " + name + " => " + notch); 99 | ClassNode optiNode = toDeobfClassNode(optiClass); 100 | 101 | ClassWriter classWriter = new ClassWriter(0); 102 | optiNode.accept(classWriter); 103 | return classWriter.toByteArray(); 104 | } 105 | } catch (IOException e) { 106 | throw new RuntimeException("Getting Optifine version of " + name, e); 107 | } 108 | } 109 | } 110 | 111 | return basicClass; 112 | } 113 | 114 | private ClassNode toDeobfClassNode(byte[] code) { 115 | ClassNode transformedNode = new ClassNode(); 116 | new ClassReader(code).accept(new RemappingClassAdapter(transformedNode, mappings), ClassReader.EXPAND_FRAMES); 117 | return transformedNode; 118 | } 119 | } -------------------------------------------------------------------------------- /src/debug/java/org/dimdev/testmod/WhiteFluid.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.testmod; 2 | 3 | import net.minecraft.block.BlockFlowingFluid; 4 | import net.minecraft.block.state.IBlockState; 5 | import net.minecraft.client.Minecraft; 6 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 7 | import net.minecraft.fluid.FlowingFluid; 8 | import net.minecraft.fluid.Fluid; 9 | import net.minecraft.fluid.IFluidState; 10 | import net.minecraft.init.Items; 11 | import net.minecraft.init.Particles; 12 | import net.minecraft.item.Item; 13 | import net.minecraft.particles.IParticleData; 14 | import net.minecraft.state.StateContainer; 15 | import net.minecraft.util.BlockRenderLayer; 16 | import net.minecraft.util.EnumFacing; 17 | import net.minecraft.util.ResourceLocation; 18 | import net.minecraft.util.math.BlockPos; 19 | import net.minecraft.util.math.MathHelper; 20 | import net.minecraft.world.IWorld; 21 | import net.minecraft.world.IWorldReader; 22 | import net.minecraft.world.IWorldReaderBase; 23 | import net.minecraft.world.World; 24 | import org.dimdev.rift.injectedmethods.RiftFluid; 25 | 26 | import javax.annotation.Nullable; 27 | import java.util.Random; 28 | 29 | public abstract class WhiteFluid extends FlowingFluid implements RiftFluid { 30 | public WhiteFluid() {} 31 | 32 | @Override 33 | public Fluid getFlowingFluid() { 34 | return TestMod.FLOWING_WHITE_FLUID; 35 | } 36 | 37 | @Override 38 | public Fluid getStillFluid() { 39 | return TestMod.WHITE_FLUID; 40 | } 41 | 42 | @Override 43 | public BlockRenderLayer getRenderLayer() { 44 | return BlockRenderLayer.SOLID; 45 | } 46 | 47 | @Override 48 | public Item getFilledBucket() { 49 | return Items.WATER_BUCKET; 50 | } 51 | 52 | @Override 53 | protected void randomTick(World world, BlockPos pos, IFluidState state, Random random) { 54 | } 55 | 56 | @Override @Nullable 57 | public IParticleData getDripParticleData() { 58 | return Particles.DRIPPING_WATER; 59 | } 60 | 61 | @Override 62 | protected boolean canSourcesMultiply() { 63 | return true; 64 | } 65 | 66 | @Override 67 | protected void beforeReplacingBlock(IWorld world, BlockPos pos, IBlockState state) { 68 | state.dropBlockAsItem(world.getWorld(), pos, 0); 69 | } 70 | 71 | @Override 72 | public int getSlopeFindDistance(IWorldReaderBase worldIn) { 73 | return 4; 74 | } 75 | 76 | @Override 77 | public IBlockState getBlockState(IFluidState state) { 78 | return TestMod.BLOCK_WHITE_FLUID.getDefaultState().with(BlockFlowingFluid.LEVEL, getLevelFromState(state)); 79 | } 80 | 81 | @Override 82 | public boolean isEquivalentTo(Fluid fluid) { 83 | return fluid == TestMod.WHITE_FLUID || fluid == TestMod.FLOWING_WHITE_FLUID; 84 | } 85 | 86 | @Override 87 | public int getLevelDecreasePerBlock(IWorldReaderBase world) { 88 | return 1; 89 | } 90 | 91 | @Override 92 | public int getTickRate(IWorldReaderBase world) { 93 | return 5; 94 | } 95 | 96 | @Override 97 | public boolean canOtherFlowInto(IFluidState state, Fluid fluid, EnumFacing direction) { 98 | return false; 99 | } 100 | 101 | @Override 102 | protected float getExplosionResistance() { 103 | return 100.0F; 104 | } 105 | 106 | @Override 107 | public TextureAtlasSprite getStillTexture() { 108 | return Minecraft.getInstance().getModelManager().getBlockModelShapes().getModel(TestMod.BLOCK_WHITE_FLUID.getDefaultState()).getParticleTexture(); 109 | } 110 | 111 | @Override 112 | public TextureAtlasSprite getFlowingTexture() { 113 | return Minecraft.getInstance().getTextureMap().getSprite(new ResourceLocation("testmod", "block/white_fluid_flow")); 114 | } 115 | 116 | @Override 117 | public int getColorMultiplier(IWorldReader world, BlockPos pos) { 118 | int brightness = (int) MathHelper.clamp(255 * ((pos.getY() - 50) / 20.0), 0, 255); 119 | return (brightness << 16) + (brightness << 8) + brightness; 120 | } 121 | 122 | public static class Flowing extends WhiteFluid { 123 | public Flowing() {} 124 | 125 | @Override 126 | protected void fillStateContainer(StateContainer.Builder builder) { 127 | super.fillStateContainer(builder); 128 | builder.add(LEVEL_1_8); 129 | } 130 | 131 | @Override 132 | public int getLevel(IFluidState getLevel) { 133 | return getLevel.get(LEVEL_1_8); 134 | } 135 | 136 | @Override 137 | public boolean isSource(IFluidState state) { 138 | return false; 139 | } 140 | } 141 | 142 | public static class Source extends WhiteFluid { 143 | public Source() {} 144 | 145 | @Override 146 | public int getLevel(IFluidState getLevel) { 147 | return 8; 148 | } 149 | 150 | @Override 151 | public boolean isSource(IFluidState state) { 152 | return true; 153 | } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/debug/java/org/dimdev/testmod/TestMod.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.testmod; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | 5 | import net.minecraft.block.Block; 6 | import net.minecraft.block.BlockFlowingFluid; 7 | import net.minecraft.block.BlockStainedGlass; 8 | import net.minecraft.block.material.Material; 9 | import net.minecraft.client.Minecraft; 10 | import net.minecraft.client.audio.MusicTicker.MusicType; 11 | import net.minecraft.command.CommandSource; 12 | import net.minecraft.fluid.FlowingFluid; 13 | import net.minecraft.fluid.Fluid; 14 | import net.minecraft.item.EnumDyeColor; 15 | import net.minecraft.item.Item; 16 | import net.minecraft.item.ItemGroup; 17 | import net.minecraft.network.EnumPacketDirection; 18 | import net.minecraft.util.ResourceLocation; 19 | import net.minecraft.util.registry.IRegistry; 20 | 21 | import org.apache.logging.log4j.LogManager; 22 | import org.apache.logging.log4j.Logger; 23 | 24 | import org.dimdev.rift.listener.*; 25 | import org.dimdev.rift.listener.client.AmbientMusicTypeProvider; 26 | import org.dimdev.rift.listener.client.ClientTickable; 27 | import org.dimdev.rift.listener.client.TextureAdder; 28 | import org.dimdev.rift.network.Message; 29 | 30 | import java.util.Collection; 31 | import java.util.Collections; 32 | 33 | import static net.minecraft.init.SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP; 34 | 35 | public class TestMod implements BlockAdder, ItemAdder, FluidAdder, TextureAdder, PacketAdder, CommandAdder, ClientTickable, AmbientMusicTypeProvider, DimensionTypeAdder, MessageAdder { 36 | private static final Logger LOGGER = LogManager.getLogger(); 37 | public static final Block WHITE_BLOCK = new Block(Block.Properties.create(Material.ROCK)); 38 | public static final Block TRANSLUCENT_WHITE_BLOCK = new BlockStainedGlass(EnumDyeColor.WHITE, Block.Properties.create(Material.GLASS)); 39 | public static final FlowingFluid WHITE_FLUID = new WhiteFluid.Source(); 40 | public static final FlowingFluid FLOWING_WHITE_FLUID = new WhiteFluid.Flowing(); 41 | public static final BlockFlowingFluid BLOCK_WHITE_FLUID = new BlockFlowingFluid(WHITE_FLUID, Block.Properties.create(Material.WATER).doesNotBlockMovement().hardnessAndResistance(100F, 100F).variableOpacity()); 42 | public static final Item PACKET_TESTER = new ItemPacketTester(new Item.Properties()); 43 | public static final MusicType TEST_MUSIC = AmbientMusicTypeProvider.newMusicType("test", ENTITY_EXPERIENCE_ORB_PICKUP, 0, 0); 44 | private int clientTickCount = 0, inWorldTicks = 0; 45 | 46 | @Override 47 | public void registerBlocks() { 48 | Block.register(new ResourceLocation("testmod", "white_block"), WHITE_BLOCK); 49 | Block.register(new ResourceLocation("testmod", "translucent_white_block"), TRANSLUCENT_WHITE_BLOCK); 50 | Block.register(new ResourceLocation("testmod", "white_fluid"), BLOCK_WHITE_FLUID); 51 | } 52 | 53 | @Override 54 | public void registerItems() { 55 | Item.register(WHITE_BLOCK, ItemGroup.BUILDING_BLOCKS); 56 | Item.register(TRANSLUCENT_WHITE_BLOCK, ItemGroup.BUILDING_BLOCKS); 57 | Item.register(new ResourceLocation("testmod", "packet_tester"), PACKET_TESTER); 58 | } 59 | 60 | @Override 61 | public void registerFluids() { 62 | Fluid.register(new ResourceLocation("testmod", "white_fluid"), WHITE_FLUID); 63 | Fluid.register(new ResourceLocation("testmod", "flowing_white_fluid"), FLOWING_WHITE_FLUID); 64 | } 65 | 66 | @Override 67 | public Collection getBuiltinTextures() { 68 | return Collections.singletonList(new ResourceLocation("testmod", "block/white_fluid_flow")); 69 | } 70 | 71 | @Override 72 | public void registerHandshakingPackets(PacketRegistrationReceiver receiver) {} 73 | 74 | @Override 75 | public void registerPlayPackets(PacketRegistrationReceiver receiver) { 76 | receiver.registerPacket(EnumPacketDirection.SERVERBOUND, CPacketTest.class); 77 | } 78 | 79 | @Override 80 | public void registerStatusPackets(PacketRegistrationReceiver receiver) {} 81 | 82 | @Override 83 | public void registerLoginPackets(PacketRegistrationReceiver receiver) {} 84 | 85 | @Override 86 | public void registerCommands(CommandDispatcher dispatcher) { 87 | ExplosionCommand.register(dispatcher); 88 | ChangeDimensionCommand.register(dispatcher); 89 | } 90 | 91 | @Override 92 | public void clientTick(Minecraft client) { 93 | if (clientTickCount++ == 100) { 94 | LOGGER.info("100 ticks have passed"); 95 | } 96 | if (client.world != null) { 97 | inWorldTicks++; 98 | } else if (inWorldTicks > 0) { 99 | inWorldTicks = 0; 100 | } 101 | } 102 | 103 | @Override 104 | public MusicType getAmbientMusicType(Minecraft client) { 105 | //Make some experience noises for 100 ticks but then stop because they are very annoying 106 | return inWorldTicks < 100 ? TEST_MUSIC : null; 107 | } 108 | 109 | @Override 110 | public void registerDimensionTypes() { 111 | TestDimension.giveType(DimensionTypeAdder.addDimensionType(555, new ResourceLocation("testmod", "test_dimension"), "_test", TestDimension::new)); 112 | } 113 | 114 | @Override 115 | public void registerMessages(IRegistry> registry) { 116 | registry.put(new ResourceLocation("testmod", "test_message"), TestMessage.class); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/rift/resources/ModPack.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.rift.resources; 2 | 3 | import com.google.common.collect.Lists; 4 | import net.minecraft.resources.AbstractResourcePack; 5 | import net.minecraft.resources.ResourcePackType; 6 | import net.minecraft.util.ResourceLocation; 7 | import org.apache.logging.log4j.LogManager; 8 | import org.apache.logging.log4j.Logger; 9 | 10 | import java.io.File; 11 | import java.io.FileNotFoundException; 12 | import java.io.IOException; 13 | import java.io.InputStream; 14 | import java.net.URI; 15 | import java.net.URISyntaxException; 16 | import java.net.URL; 17 | import java.nio.file.*; 18 | import java.util.*; 19 | import java.util.function.Predicate; 20 | 21 | public class ModPack extends AbstractResourcePack { 22 | private final String root; 23 | private final String name; 24 | private Logger LOGGER = LogManager.getLogger(); 25 | 26 | public ModPack(String name, URL root) { 27 | super(null); 28 | this.name = name; 29 | this.root = root.toString(); 30 | } 31 | 32 | @Override 33 | protected InputStream getInputStream(String path) throws IOException { 34 | return new URL(root + path).openStream(); 35 | } 36 | 37 | @Override 38 | protected boolean resourceExists(String path) { 39 | try (InputStream ignored = getInputStream(path)) { 40 | return true; 41 | } catch (IOException e) { 42 | return false; 43 | } 44 | } 45 | 46 | @Override 47 | public Collection getAllResourceLocations(ResourcePackType type, String path, int maxDepth, Predicate filter) { 48 | Set resourceLocations = new HashSet<>(); 49 | for (String namespace : getResourceNamespaces(type)) { 50 | resourceLocations.addAll(getAllResourceLocations(type, new ResourceLocation(namespace, path), maxDepth, filter)); 51 | } 52 | return resourceLocations; 53 | } 54 | 55 | public Collection getAllResourceLocations(ResourcePackType type, ResourceLocation location, int maxDepth, Predicate filter) { 56 | Set resourceLocations = new HashSet<>(); 57 | 58 | try { 59 | String path = String.format("%s/%s/%s", type.getDirectoryName(), location.getNamespace(), location.getPath()); 60 | URI url = new URL(root + path).toURI(); 61 | if ("file".equals(url.getScheme())) { 62 | resourceLocations.addAll(getAllResourceLocations(maxDepth, location, Paths.get(url), filter)); 63 | } else if ("jar".equals(url.getScheme())) { 64 | try (FileSystem fileSystem = FileSystems.newFileSystem(url, Collections.emptyMap())) { 65 | resourceLocations.addAll(getAllResourceLocations(maxDepth, location, fileSystem.getPath(path), filter)); 66 | } 67 | } else { 68 | LOGGER.error("Unsupported scheme " + url + " trying to list mod resources"); 69 | } 70 | } catch (NoSuchFileException | FileNotFoundException ignored) { 71 | } catch (IOException | URISyntaxException e) { 72 | LOGGER.error("Couldn't get a list of all resources of '" + getName() + "'", e); 73 | } 74 | 75 | return resourceLocations; 76 | } 77 | 78 | private static Collection getAllResourceLocations(int maxDepth, ResourceLocation rootLocation, Path rootPath, Predicate filter) throws IOException { 79 | List resourceLocations = Lists.newArrayList(); 80 | Iterator pathIterator = Files.walk(rootPath, maxDepth).iterator(); 81 | 82 | while (pathIterator.hasNext()) { 83 | Path path = pathIterator.next(); 84 | if (!path.endsWith(".mcmeta") && Files.isRegularFile(path) && filter.test(path.getFileName().toString())) { 85 | resourceLocations.add(new ResourceLocation(rootLocation.getNamespace(), rootLocation.getPath() + "/" + rootPath.toAbsolutePath().relativize(path).toString().replaceAll("\\\\", "/"))); 86 | } 87 | } 88 | 89 | return resourceLocations; 90 | } 91 | 92 | @Override 93 | public Set getResourceNamespaces(ResourcePackType type) { 94 | try { 95 | URI uri = new URL(root + type.getDirectoryName() + "/").toURI(); 96 | if ("file".equals(uri.getScheme())) { 97 | Set namespaces = new HashSet<>(); 98 | File rootFile = new File(uri); 99 | if (rootFile.isDirectory()) { 100 | for (File file : rootFile.listFiles()) { 101 | namespaces.add(file.getName()); 102 | } 103 | } 104 | return namespaces; 105 | } else if ("jar".equals(uri.getScheme())) { 106 | try (FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap()); 107 | DirectoryStream directoryStream = fileSystem.provider().newDirectoryStream(fileSystem.getPath(type.getDirectoryName()), x -> true)) { 108 | Set namespaces = new HashSet<>(); 109 | for (Path p : directoryStream) { 110 | String fileName = p.getFileName().toString(); 111 | namespaces.add(fileName.substring(0, fileName.length() - 1)); 112 | } 113 | return namespaces; 114 | } 115 | } else { 116 | LOGGER.error("Unsupported scheme " + uri + " trying to list mod resource namespaces"); 117 | } 118 | } catch (NoSuchFileException | FileNotFoundException | NotDirectoryException ignored) { 119 | } catch (IOException | URISyntaxException e) { 120 | LOGGER.error("Couldn't get a list of resource namespaces of '" + getName() + "'", e); 121 | } 122 | 123 | return Collections.emptySet(); 124 | } 125 | 126 | @Override 127 | public void close() {} 128 | 129 | @Override 130 | public String getName() { 131 | return name; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rift 2 | Rift is a lightweight modding API, library, and mod loader for Minecraft 1.13. The main objective of Rift is to make a more modular and lightweight modding API for Minecraft. Find out more on [CurseForge](https://minecraft.curseforge.com/projects/rift). 3 | 4 | This fork contains the Minecraft 1.13.1 port (in the `newerer` branch) and the Minecraft 1.13.2 port (in the `newerest` branch). For Minecraft 1.13 see [**here**](https://github.com/DimensionalDevelopment/Rift). Pull requests should go to either of those branches depending on Minecraft version, `jitpack` is for temporary publishing until everything is pulled into the main Rift repo. 5 | 6 | 7 | ## Playing on Minecraft 1.13.2 8 | If you have any problems or find any incompatibilities using this please do report them [here](https://github.com/Chocohead/Rift/issues). Previous problems with Optifine and water/connected textures appear to have been fixed so there is nothing known to cause trouble at the moment. 9 | 10 | ### Using the Minecraft Launcher 11 | The current version can be downloaded from [**here**](https://jitpack.io/com/github/Chocohead/Rift/jitpack-SNAPSHOT/Rift-jitpack-SNAPSHOT.jar) and installed just like the previous versions of Rift. Mods designed for 1.13 currently aren't supported but might be in future. 12 | 13 | ### Using MultiMC 14 | Modified original documentation from the [Rift Wiki](https://github.com/DimensionalDevelopment/Rift/wiki/Installing-Rift-in-a-MultiMC-instance#alternate-method) 15 | 16 | 1. Make a new instance in MultiMC with with the wanted version of Minecraft—in our case, Minecraft 1.13.2 17 | 1. Click `Edit Instance`—it should open the `Version` page of the instance. 18 | 1. Click `Add Empty`. 19 | 1. Set uid to `org.dimdev.rift` and name to `Rift`. 20 | 1. Select the newly created component and click `Edit`—this should open the file in a text editor. 21 | 1. Edit the JSON to look like the example below, then save the file. 22 | 1. Launch the instance from MultiMC. 23 | 24 | The version that I selected for the example is the one provided alongside VoxelMap [here](https://minecraft.curseforge.com/projects/voxelmap) 25 | 26 | If the example doesn't fit the Rift version exactly, change the version. For example, replace all occurrences of `2d8bb9bd56` with `d6893ec777`. 27 | 28 | You can use the version page to check the file for errors—obvious mistakes will show up in the `Version` page as soon as you click the `Refresh` button. 29 | 30 | If the JSON file doesn't open in a text editor, make sure your operating system is set up to open `.json` files in one first. 31 | 32 | #### Example MultiMC Json 33 | 34 | ```json 35 | { 36 | "+tweakers": [ 37 | "org.dimdev.riftloader.launch.RiftLoaderClientTweaker" 38 | ], 39 | "formatVersion": 1, 40 | "+libraries": [ 41 | { 42 | "name": "com.github.Chocohead:rift:2d8bb9bd56", 43 | "url": "https://jitpack.io/" 44 | }, 45 | { 46 | "name": "org.dimdev:mixin:0.7.11-SNAPSHOT", 47 | "url": "https://www.dimdev.org/maven/" 48 | }, 49 | { 50 | "name": "org.ow2.asm:asm:6.2", 51 | "url": "http://repo1.maven.org/maven2/" 52 | }, 53 | { 54 | "name": "org.ow2.asm:asm-commons:6.2", 55 | "url": "http://repo1.maven.org/maven2/" 56 | }, 57 | { 58 | "name": "org.ow2.asm:asm-tree:6.2", 59 | "url": "http://repo1.maven.org/maven2/" 60 | }, 61 | { 62 | "name": "net.minecraft:launchwrapper:1.12" 63 | } 64 | ], 65 | "mainClass": "net.minecraft.launchwrapper.Launch", 66 | "name": "Rift", 67 | "releaseTime": "2018-07-18T15:11:46+00:00", 68 | "requires": [ 69 | { 70 | "equals": "1.13.2", 71 | "uid": "net.minecraft" 72 | } 73 | ], 74 | "uid": "org.dimdev.rift", 75 | "version": "1.0.4-2d8bb9bd56" 76 | } 77 | ``` 78 | 79 | ## Modding on Minecraft 1.13.2 80 | The fork of Forge Gradle 2 used for 1.13 has been improved for 1.13.2 so `setupDecompWorkspace` is now supported and is strongly encouraged to be used. Access transformers which would have otherwise silently failed will now explicitly crash so they can be fixed, which is helpful for updating. The locations of all found transformers can be found by running `setupDecompWorkspace`/`setupDevWorkspace` with `--info` and looking immediately after where the access transformer task is applied. Further improvements can be suggested [**here**](https://github.com/Chocohead/ForgeGradle/issues). 81 | 82 | Any suggestions for Rift itself can be made as issues [here](https://github.com/Chocohead/Rift/issues), or pull requested directly. Feel free to join the [Discord server](https://discord.gg/f27hdrM) if you want to talk about stuff first or have any other questions. 83 | 84 | 85 | ### Setting up 86 | For a bare bones setup which is ready to be tinkered with, see the [**Rift MDK**](https://github.com/DimensionalDevelopment/Rift-MDK/tree/1.13.2) ([download](https://github.com/DimensionalDevelopment/Rift-MDK/archive/1.13.2.zip)). 87 | 88 | If you want to start from scratch, use this `build.gradle` in favour of the [Rift wiki's](https://github.com/DimensionalDevelopment/Rift/wiki/Making-mods-with-Rift#mod-structure), otherwise the information provided there is still accurate. 89 | ```groovy 90 | buildscript { 91 | repositories { 92 | mavenCentral() 93 | maven { url 'https://www.jitpack.io' } 94 | maven { url 'https://files.minecraftforge.net/maven' } 95 | } 96 | dependencies { 97 | classpath 'com.github.Chocohead:ForgeGradle:moderniser-SNAPSHOT' 98 | } 99 | } 100 | 101 | apply plugin: 'net.minecraftforge.gradle.tweaker-client' 102 | apply plugin: 'java' 103 | 104 | group 'com.example' 105 | version '1.0.0' 106 | archivesBaseName = 'exampleMod' 107 | 108 | sourceCompatibility = 1.8 109 | targetCompatibility = 1.8 110 | 111 | repositories { 112 | mavenCentral() 113 | maven { url 'https://www.dimdev.org/maven/' } 114 | maven { url 'https://www.jitpack.io' } 115 | maven { url 'http://repo.strezz.org/artifactory/list/Strezz-Central' } 116 | } 117 | 118 | dependencies { 119 | implementation 'com.github.Chocohead:Rift:jitpack-SNAPSHOT:dev' 120 | } 121 | 122 | minecraft { 123 | version = '1.13.2' 124 | mappings = 'snapshot_20181130' 125 | runDir = 'run' 126 | tweakClass = 'org.dimdev.riftloader.launch.RiftLoaderClientTweaker' 127 | } 128 | ``` 129 | Remember to change the `group` and `archivesBaseName` for the mod you're making before publishing. 130 | 131 | 132 | ### Changes between Rift 1.13 and 1.13.2 133 | Obviously the obfuscated mappings have changed so any access transformers will need to be updated. There is the beginnings of a tool provided for automatically doing this [here](https://github.com/Chocohead/Rift/blob/newerest/src/debug/java/com/chocohead/rift/AccessTransformerUpdater.java). The same tool can also be used for more easily adding access transformer entries as it can go straight from MCP name to matching Notch names. 134 | 135 | There have also been a few API changes within Rift to account for changes made in Minecraft 1.13.1: 136 | * The deprecated `CustomPayloadHandler` has been removed in favour of using `MessageAdder` 137 | * `DimensionTypeAdder` no longer expects a set of `DimensionType`s but is a callback for registering them directly now `DimensionType` is not an enum. It provides a utility method `addDimensionType` for this purpose. 138 | * `ClientTickable#tick` now provides the `Minecraft` client instance directly to match `ServerTickable#tick` providing `MinecraftServer` 139 | 140 | There's been many MCP method name changes too but most (if not all) are obvious enough to not need listing here. 141 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/riftloader/Main.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.riftloader; 2 | 3 | import net.minecraft.launchwrapper.Launch; 4 | import org.dimdev.utils.ReflectionUtils; 5 | 6 | import javax.swing.*; 7 | import java.io.*; 8 | import java.net.URL; 9 | import java.nio.channels.Channels; 10 | import java.nio.file.Files; 11 | import java.nio.file.Paths; 12 | import java.nio.file.StandardCopyOption; 13 | import java.util.*; 14 | 15 | public class Main { 16 | private static final String[] LIBRARIES = { 17 | "https://www.dimdev.org/maven/org/dimdev/mixin/0.7.11-SNAPSHOT/mixin-0.7.11-SNAPSHOT.jar", 18 | "https://repo1.maven.org/maven2/org/ow2/asm/asm/6.2/asm-6.2.jar", 19 | "https://repo1.maven.org/maven2/org/ow2/asm/asm-commons/6.2/asm-commons-6.2.jar", 20 | "https://repo1.maven.org/maven2/org/ow2/asm/asm-tree/6.2/asm-tree-6.2.jar", 21 | "https://libraries.minecraft.net/net/minecraft/launchwrapper/1.12/launchwrapper-1.12.jar" 22 | }; 23 | public static final String VANILLA_SERVER = "https://launcher.mojang.com/v1/objects/3737db93722a9e39eeada7c27e7aca28b144ffa7/server.jar"; 24 | // public static final String SPIGOT_SERVER = "https://cdn.getbukkit.org/spigot/spigot-1.13.jar"; 25 | 26 | public static void main(String... args) throws Throwable { 27 | if (args.length == 0) { 28 | runClientInstaller(false); 29 | } else if (args[0].equals("--install")) { 30 | runClientInstaller(true); 31 | } else if (args[0].equals("--server")) { 32 | File serverJar = new File("server.jar"); 33 | if (!serverJar.isFile()) { 34 | System.out.println("File 'server.jar' does not exist"); 35 | System.out.println("Choose which server you'd like to download:"); 36 | System.out.println(" 1) Vanilla"); 37 | // System.out.println(" 2) Spigot"); 38 | System.out.print("Choice: "); 39 | 40 | URL url; 41 | String line = new Scanner(System.in).nextLine().toLowerCase(); 42 | if (line.startsWith("1") || line.startsWith("v")) { 43 | url = new URL(VANILLA_SERVER); 44 | // } else if (line.startsWith("2") || line.startsWith("s")) { 45 | // url = new URL(SPIGOT_SERVER); 46 | } else { 47 | System.err.println("Not a valid choice"); 48 | return; 49 | } 50 | 51 | System.out.println("Downloading server jar: " + url); 52 | new FileOutputStream(serverJar).getChannel().transferFrom(Channels.newChannel(url.openStream()), 0, Long.MAX_VALUE); 53 | } 54 | 55 | ReflectionUtils.addURLToClasspath(serverJar.toURI().toURL()); 56 | 57 | for (String url : LIBRARIES) { 58 | ReflectionUtils.addURLToClasspath(getOrDownload(new File("libs"), new URL(url)).toURI().toURL()); 59 | } 60 | 61 | List argsList = new ArrayList<>(Arrays.asList(args).subList(1, args.length)); 62 | argsList.add("--tweakClass"); 63 | argsList.add("org.dimdev.riftloader.launch.RiftLoaderServerTweaker"); 64 | 65 | System.out.println("Launching server..."); 66 | Launch.main(argsList.toArray(new String[0])); 67 | } 68 | } 69 | 70 | private static File getOrDownload(File directory, URL url) throws IOException { 71 | String urlString = url.toString(); 72 | File target = new File(directory, urlString.substring(urlString.lastIndexOf('/') + 1)); 73 | if (target.isFile()) { 74 | return target; 75 | } 76 | target.getParentFile().mkdirs(); 77 | 78 | System.out.println("Downloading library: " + urlString); 79 | new FileOutputStream(target).getChannel().transferFrom(Channels.newChannel(url.openStream()), 0, Long.MAX_VALUE); 80 | 81 | return target; 82 | } 83 | 84 | public static void runClientInstaller(boolean ask) { 85 | try { 86 | UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 87 | } catch (Throwable t) { 88 | t.printStackTrace(); 89 | } 90 | 91 | try { 92 | File minecraftFolder; 93 | String osName = System.getProperty("os.name").toLowerCase(Locale.ROOT); 94 | if (osName.contains("win")) { 95 | minecraftFolder = new File(System.getenv("APPDATA") + "/.minecraft"); 96 | } else if (osName.contains("mac")) { 97 | minecraftFolder = new File(System.getProperty("user.home") + "/Library/Application Support/minecraft"); 98 | } else { 99 | minecraftFolder = new File(System.getProperty("user.home") + "/.minecraft"); 100 | } 101 | 102 | if (ask) { 103 | JFileChooser dlg = new JFileChooser(minecraftFolder); 104 | dlg.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 105 | dlg.setDialogTitle("Select install directory"); 106 | int res = dlg.showOpenDialog(null); 107 | if (res == JFileChooser.APPROVE_OPTION) { 108 | minecraftFolder = dlg.getSelectedFile(); 109 | } else { 110 | return; //Cancelled picking an install directory 111 | } 112 | } 113 | 114 | // Copy the version json 115 | File versionJson = new File(minecraftFolder, "versions/1.13.2-rift-@VERSION@/1.13.2-rift-@VERSION@.json"); 116 | versionJson.getParentFile().mkdirs(); 117 | Files.copy(Main.class.getResourceAsStream("/profile.json"), versionJson.toPath(), StandardCopyOption.REPLACE_EXISTING); 118 | 119 | File fakeJar = new File(minecraftFolder, "versions/1.13.2-rift-@VERSION@/1.13.2-rift-@VERSION@.jar"); 120 | if (!fakeJar.exists()) { 121 | File maybeRealJar = new File(minecraftFolder, "versions/1.13.2/1.13.2.jar"); 122 | if (maybeRealJar.exists()) { 123 | Files.copy(maybeRealJar.toPath(), fakeJar.toPath(), StandardCopyOption.REPLACE_EXISTING); 124 | } else { 125 | fakeJar.createNewFile(); 126 | } 127 | } 128 | 129 | // Make mods directory 130 | try { 131 | File modsFolder = new File(minecraftFolder, "mods"); 132 | modsFolder.mkdirs(); 133 | } catch (Throwable t) { 134 | t.printStackTrace(); 135 | } 136 | 137 | // Add rift as a profile 138 | try { 139 | File profilesJson = new File(minecraftFolder, "launcher_profiles.json"); 140 | if (profilesJson.exists()) { // TODO: use gson instead 141 | String contents = new String(Files.readAllBytes(profilesJson.toPath())); 142 | if (contents.contains("\"rift\"")) { 143 | contents = contents.replaceAll(",\n *\"rift\": \\{[^}]*},", ","); 144 | contents = contents.replaceAll(",?\n *\"rift\": \\{[^}]*},?", ""); 145 | } 146 | if (contents.contains("\"Rift\"")) { 147 | contents = contents.replaceAll(",\n *\"Rift\": \\{[^}]*},", ","); 148 | contents = contents.replaceAll(",?\n *\"Rift\": \\{[^}]*},?", ""); 149 | } 150 | 151 | contents = contents.replace("\n \"profiles\": {", "\n \"profiles\": {\n" + 152 | " \"Rift\": {\n" + 153 | " \"name\": \"Rift\",\n" + 154 | " \"type\": \"custom\",\n" + 155 | " \"created\": \"2018-08-13T00:00:00.000Z\",\n" + 156 | " \"lastUsed\": \"2100-01-01T00:00:00.000Z\",\n" + 157 | " \"lastVersionId\": \"1.13.2-rift-@VERSION@\"\n" + 158 | " },"); 159 | 160 | Files.write(profilesJson.toPath(), contents.getBytes()); 161 | } 162 | } catch (Throwable t) { 163 | t.printStackTrace(); 164 | } 165 | 166 | // Copy rift jar to libraries 167 | try { 168 | String source = Main.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 169 | if (source.startsWith("/") && osName.contains("win")) { 170 | source = source.substring(1); 171 | } 172 | File riftJar = new File(minecraftFolder, "libraries/org/dimdev/rift/@VERSION@/rift-@VERSION@.jar"); 173 | riftJar.getParentFile().mkdirs(); 174 | Files.copy(Paths.get(source), riftJar.toPath(), StandardCopyOption.REPLACE_EXISTING); 175 | } catch (Throwable t) { 176 | t.printStackTrace(); 177 | } 178 | 179 | JOptionPane.showMessageDialog(null, 180 | "Rift @VERSION@ for Minecraft 1.13.2 has been successfully installed" + 181 | (ask ? " to\n" + minecraftFolder.getAbsolutePath() + "\n" : "!\n") + 182 | "\n" + 183 | "It is available in the dropdown menu of the vanilla Minecraft launcher.\n" + 184 | "You'll need to restart the Minecraft Launcher if you had it open when\n" + 185 | "you ran this installer.", 186 | "Rift Installer", JOptionPane.INFORMATION_MESSAGE); 187 | } catch (Throwable t) { 188 | StringWriter w = new StringWriter(); 189 | t.printStackTrace(new PrintWriter(w)); 190 | JOptionPane.showMessageDialog(null, 191 | "An error occured while installing Rift, please report this to the issue\n" + 192 | "tracker (https://github.com/DimensionalDevelopment/Rift/issues):\n" + 193 | "\n" + 194 | w.toString().replace("\t", " "), "Rift Installer", JOptionPane.ERROR_MESSAGE); 195 | } 196 | } 197 | } 198 | --------------------------------------------------------------------------------