diff --git a/dependencies.gradle b/dependencies.gradle index 19c61a2..f68fcfa 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -75,6 +75,9 @@ dependencies { //Immersive Cavegen 1.2g compile(deobfCurse("immersivecavegen-521557:3649411")) + //LOTR Mod 36.14 + compileOnly(deobfCurse("lotrmod-423748:3646430")) + //More Fun Quicksands Mod 1.0.8.8-fixed compileOnly(deobfCurse("more-fun-quicksand-mod-321960:2717318")) diff --git a/src/main/java/com/falsepattern/endlessids/mixin/helpers/LOTRBiomeVariantStorageShort.java b/src/main/java/com/falsepattern/endlessids/mixin/helpers/LOTRBiomeVariantStorageShort.java new file mode 100644 index 0000000..c6f0abf --- /dev/null +++ b/src/main/java/com/falsepattern/endlessids/mixin/helpers/LOTRBiomeVariantStorageShort.java @@ -0,0 +1,139 @@ +package com.falsepattern.endlessids.mixin.helpers; + +import com.falsepattern.endlessids.Hooks; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.val; +import lotr.common.LOTRDimension; +import lotr.common.network.LOTRPacketBiomeVariantsUnwatch; +import lotr.common.network.LOTRPacketBiomeVariantsWatch; +import lotr.common.network.LOTRPacketHandler; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraft.world.chunk.Chunk; +import cpw.mods.fml.common.FMLLog; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class LOTRBiomeVariantStorageShort { + private static final Map> chunkVariantMap = new HashMap<>(); + private static final Map> chunkVariantMapClient = new HashMap<>(); + + private static Map getDimensionChunkMap(World world) { + Map> sourcemap; + if (!world.isRemote) { + sourcemap = chunkVariantMap; + } else { + sourcemap = chunkVariantMapClient; + } + + val dim = LOTRDimension.getCurrentDimensionWithFallback(world); + + return sourcemap.computeIfAbsent(dim, k -> new HashMap<>()); + } + + private static ChunkCoordIntPair getChunkKey(Chunk chunk) { + return new ChunkCoordIntPair(chunk.xPosition, chunk.zPosition); + } + + public static short[] getChunkBiomeVariants(World world, Chunk chunk) { + return getChunkBiomeVariants(world, getChunkKey(chunk)); + } + + public static short[] getChunkBiomeVariants(World world, ChunkCoordIntPair chunk) { + return getDimensionChunkMap(world).get(chunk); + } + + public static void setChunkBiomeVariants(World world, Chunk chunk, short[] variants) { + setChunkBiomeVariants(world, getChunkKey(chunk), variants); + } + + public static void setChunkBiomeVariants(World world, ChunkCoordIntPair chunk, short[] variants) { + getDimensionChunkMap(world).put(chunk, variants); + } + + public static void clearChunkBiomeVariants(World world, Chunk chunk) { + clearChunkBiomeVariants(world, getChunkKey(chunk)); + } + + public static void clearChunkBiomeVariants(World world, ChunkCoordIntPair chunk) { + getDimensionChunkMap(world).remove(chunk); + } + + public static void loadChunkVariants(World world, Chunk chunk, NBTTagCompound data) { + if (getChunkBiomeVariants(world, chunk) == null) { + short[] variants; + if (data.hasKey("LOTRBiomeVariantsS")) { + variants = Hooks.byteToShortArray(data.getByteArray("LOTRBiomeVariantsS")); + } else { + variants = new short[256]; + } + + setChunkBiomeVariants(world, chunk, variants); + } + + } + + public static void saveChunkVariants(World world, Chunk chunk, NBTTagCompound data) { + val variants = getChunkBiomeVariants(world, chunk); + if (variants != null) { + data.setByteArray("LOTRBiomeVariantsS", Hooks.shortToByteArray(variants)); + } + + } + + public static void clearAllVariants(World world) { + getDimensionChunkMap(world).clear(); + FMLLog.info("Unloading LOTR biome variants in %s", + LOTRDimension.getCurrentDimensionWithFallback(world).dimensionName); + } + + public static void performCleanup(WorldServer world) { + val dimensionMap = getDimensionChunkMap(world); + val removalChunks = new ArrayList(); + + for (val chunk : dimensionMap.keySet()) { + if (!world.theChunkProviderServer.chunkExists(chunk.chunkXPos, chunk.chunkZPos)) { + removalChunks.add(chunk); + } + } + + for (val chunk : removalChunks) { + dimensionMap.remove(chunk); + } + } + + public static void sendChunkVariantsToPlayer(World world, Chunk chunk, EntityPlayerMP entityplayer) { + short[] variants = getChunkBiomeVariants(world, chunk); + if (variants != null) { + val packet = new LOTRPacketBiomeVariantsWatch(chunk.xPosition, chunk.zPosition, + Hooks.shortToByteArray(variants)); + LOTRPacketHandler.networkWrapper.sendTo(packet, entityplayer); + } else { + val dimName = world.provider.getDimensionName(); + val posX = chunk.xPosition << 4; + val posZ = chunk.zPosition << 4; + val playerName = entityplayer.getCommandSenderName(); + FMLLog.severe("Could not find LOTR biome variants for %s chunk at %d, %d; requested by %s", dimName, posX, + posZ, playerName); + } + + } + + public static void sendUnwatchToPlayer(World world, Chunk chunk, EntityPlayerMP entityplayer) { + val packet = new LOTRPacketBiomeVariantsUnwatch(chunk.xPosition, chunk.zPosition); + LOTRPacketHandler.networkWrapper.sendTo(packet, entityplayer); + } + + public static int getSize(World world) { + val map = getDimensionChunkMap(world); + return map.size(); + } +} diff --git a/src/main/java/com/falsepattern/endlessids/mixin/helpers/stubpackage/lotr/common/network/LOTRPacketBiomeVariantsWatch.java b/src/main/java/com/falsepattern/endlessids/mixin/helpers/stubpackage/lotr/common/network/LOTRPacketBiomeVariantsWatch.java new file mode 100644 index 0000000..49af0bb --- /dev/null +++ b/src/main/java/com/falsepattern/endlessids/mixin/helpers/stubpackage/lotr/common/network/LOTRPacketBiomeVariantsWatch.java @@ -0,0 +1,7 @@ +package com.falsepattern.endlessids.mixin.helpers.stubpackage.lotr.common.network; + +public class LOTRPacketBiomeVariantsWatch { + public int chunkX; + public int chunkZ; + public byte[] variants; +} diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/lotr/LOTRBiomeVariantStorageMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/lotr/LOTRBiomeVariantStorageMixin.java new file mode 100644 index 0000000..3bdf19a --- /dev/null +++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/lotr/LOTRBiomeVariantStorageMixin.java @@ -0,0 +1,140 @@ +package com.falsepattern.endlessids.mixin.mixins.common.lotr; + +import com.falsepattern.endlessids.mixin.helpers.LOTRBiomeVariantStorageShort; +import lotr.common.world.biome.variant.LOTRBiomeVariantStorage; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraft.world.chunk.Chunk; + +@Mixin(value = LOTRBiomeVariantStorage.class, + remap = false) +public abstract class LOTRBiomeVariantStorageMixin { + + private static UnsupportedOperationException crash() { + return new UnsupportedOperationException("Deprecated method."); + } + + /** + * @author FalsePattern + * @reason Fix stuff + */ + @Overwrite + public static byte[] getChunkBiomeVariants(World world, Chunk chunk) { + throw crash(); + } + + /** + * @author FalsePattern + * @reason Fix stuff + */ + @Overwrite + public static byte[] getChunkBiomeVariants(World world, ChunkCoordIntPair chunk) { + throw crash(); + } + + /** + * @author FalsePattern + * @reason Fix stuff + */ + @Overwrite + public static void setChunkBiomeVariants(World world, Chunk chunk, byte[] variants) { + throw crash(); + } + + + /** + * @author FalsePattern + * @reason Fix stuff + */ + @Overwrite + public static void setChunkBiomeVariants(World world, ChunkCoordIntPair chunk, byte[] variants) { + throw crash(); + } + + /** + * @author FalsePattern + * @reason Fix stuff + */ + @Overwrite + public static void clearChunkBiomeVariants(World world, Chunk chunk) { + LOTRBiomeVariantStorageShort.clearChunkBiomeVariants(world, chunk); + } + + /** + * @author FalsePattern + * @reason Fix stuff + */ + @Overwrite + public static void clearChunkBiomeVariants(World world, ChunkCoordIntPair chunk) { + LOTRBiomeVariantStorageShort.clearChunkBiomeVariants(world, chunk); + } + + /** + * @author FalsePattern + * @reason Fix stuff + */ + @Overwrite + public static void loadChunkVariants(World world, Chunk chunk, NBTTagCompound data) { + LOTRBiomeVariantStorageShort.loadChunkVariants(world, chunk, data); + } + + /** + * @author FalsePattern + * @reason Fix stuff + */ + @Overwrite + public static void saveChunkVariants(World world, Chunk chunk, NBTTagCompound data) { + LOTRBiomeVariantStorageShort.saveChunkVariants(world, chunk, data); + } + + /** + * @author FalsePattern + * @reason Fix stuff + */ + @Overwrite + public static void clearAllVariants(World world) { + LOTRBiomeVariantStorageShort.clearAllVariants(world); + } + + /** + * @author FalsePattern + * @reason Fix stuff + */ + @Overwrite + public static void performCleanup(WorldServer world) { + LOTRBiomeVariantStorageShort.performCleanup(world); + } + + /** + * @author FalsePattern + * @reason Fix stuff + */ + @Overwrite + public static void sendChunkVariantsToPlayer(World world, Chunk chunk, EntityPlayerMP entityPlayer) { + LOTRBiomeVariantStorageShort.sendChunkVariantsToPlayer(world, chunk, entityPlayer); + } + + /** + * @author FalsePattern + * @reason Fix stuff + */ + @Overwrite + public static void sendUnwatchToPlayer(World world, Chunk chunk, EntityPlayerMP entityPlayer) { + LOTRBiomeVariantStorageShort.sendUnwatchToPlayer(world, chunk, entityPlayer); + } + + /** + * @author FalsePattern + * @reason Fix stuff + */ + @Overwrite + public static int getSize(World world) { + return LOTRBiomeVariantStorageShort.getSize(world); + } +} diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/lotr/LOTRChunkProviderMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/lotr/LOTRChunkProviderMixin.java new file mode 100644 index 0000000..d9834f0 --- /dev/null +++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/lotr/LOTRChunkProviderMixin.java @@ -0,0 +1,34 @@ +package com.falsepattern.endlessids.mixin.mixins.common.lotr; + +import com.falsepattern.endlessids.mixin.helpers.LOTRBiomeVariantStorageShort; +import lotr.common.world.LOTRChunkProvider; +import lotr.common.world.biome.variant.LOTRBiomeVariant; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; + +@Mixin(value = LOTRChunkProvider.class, + remap = false) +public abstract class LOTRChunkProviderMixin { + @Shadow + private LOTRBiomeVariant[] variantsForGeneration; + + @Redirect(method = "provideChunk", + at = @At(value = "INVOKE", + target = "Llotr/common/world/biome/variant/LOTRBiomeVariantStorage;setChunkBiomeVariants(Lnet/minecraft/world/World;Lnet/minecraft/world/chunk/Chunk;[B)V"), + remap = true, + require = 1) + private void storeShorts(World world, Chunk chunk, byte[] variantsB) { + short[] variants = new short[256]; + + for (int l = 0; l < variants.length; ++l) { + variants[l] = (short) this.variantsForGeneration[l].variantID; + } + + LOTRBiomeVariantStorageShort.setChunkBiomeVariants(world, chunk, variants); + } +} diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/lotr/LOTRChunkProviderUtumnoMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/lotr/LOTRChunkProviderUtumnoMixin.java new file mode 100644 index 0000000..f7f64c6 --- /dev/null +++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/lotr/LOTRChunkProviderUtumnoMixin.java @@ -0,0 +1,34 @@ +package com.falsepattern.endlessids.mixin.mixins.common.lotr; + +import com.falsepattern.endlessids.mixin.helpers.LOTRBiomeVariantStorageShort; +import lotr.common.world.LOTRChunkProviderUtumno; +import lotr.common.world.biome.variant.LOTRBiomeVariant; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; + +@Mixin(value = LOTRChunkProviderUtumno.class, + remap = false) +public abstract class LOTRChunkProviderUtumnoMixin { + @Shadow + private LOTRBiomeVariant[] variantsForGeneration; + + @Redirect(method = "provideChunk", + at = @At(value = "INVOKE", + target = "Llotr/common/world/biome/variant/LOTRBiomeVariantStorage;setChunkBiomeVariants(Lnet/minecraft/world/World;Lnet/minecraft/world/chunk/Chunk;[B)V"), + remap = true, + require = 1) + private void storeShorts(World world, Chunk chunk, byte[] variantsB) { + short[] variants = new short[256]; + + for (int l = 0; l < variants.length; ++l) { + variants[l] = (short) this.variantsForGeneration[l].variantID; + } + + LOTRBiomeVariantStorageShort.setChunkBiomeVariants(world, chunk, variants); + } +} diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/lotr/LOTRPacketBiomeVariantsWatchHandler.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/lotr/LOTRPacketBiomeVariantsWatchHandler.java new file mode 100644 index 0000000..1d2ad64 --- /dev/null +++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/lotr/LOTRPacketBiomeVariantsWatchHandler.java @@ -0,0 +1,43 @@ +package com.falsepattern.endlessids.mixin.mixins.common.lotr; + +import com.falsepattern.endlessids.Hooks; +import com.falsepattern.endlessids.mixin.helpers.LOTRBiomeVariantStorageShort; +import lombok.val; +import lotr.common.LOTRMod; +import lotr.common.network.LOTRPacketBiomeVariantsWatch; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; + +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.World; +import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; + +@Mixin(value = LOTRPacketBiomeVariantsWatch.Handler.class, + remap = false) +public abstract class LOTRPacketBiomeVariantsWatchHandler { + + /** + * @author FalsePattern + * @reason fix stuff + */ + @SuppressWarnings("ConstantConditions") + @Overwrite + public IMessage onMessage(LOTRPacketBiomeVariantsWatch pkt, MessageContext context) { + val packet = + (com.falsepattern.endlessids.mixin.helpers.stubpackage.lotr.common.network.LOTRPacketBiomeVariantsWatch) (Object) pkt; + World world = LOTRMod.proxy.getClientWorld(); + int chunkX = packet.chunkX; + int chunkZ = packet.chunkZ; + if (world.blockExists(chunkX << 4, 0, chunkZ << 4)) { + LOTRBiomeVariantStorageShort.setChunkBiomeVariants(world, new ChunkCoordIntPair(chunkX, chunkZ), + Hooks.byteToShortArray(packet.variants)); + } else { + FMLLog.severe("Client received LOTR biome variant data for nonexistent chunk at %d, %d", chunkX << 4, + chunkZ << 4); + } + + return null; + } +} diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/lotr/LOTRWorldChunkManagerMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/lotr/LOTRWorldChunkManagerMixin.java new file mode 100644 index 0000000..a912b45 --- /dev/null +++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/lotr/LOTRWorldChunkManagerMixin.java @@ -0,0 +1,46 @@ +package com.falsepattern.endlessids.mixin.mixins.common.lotr; + +import com.falsepattern.endlessids.mixin.helpers.LOTRBiomeVariantStorageShort; +import lotr.common.world.LOTRWorldChunkManager; +import lotr.common.world.biome.variant.LOTRBiomeVariant; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import cpw.mods.fml.common.FMLLog; + +@Mixin(value = LOTRWorldChunkManager.class, + remap = false) +public abstract class LOTRWorldChunkManagerMixin { + @Shadow + private World worldObj; + + @Shadow + public abstract LOTRBiomeVariant[] getBiomeVariants(LOTRBiomeVariant[] variants, int i, int k, int xSize, int zSize); + + /** + * @author FalsePattern + * @reason fix stuff + */ + @Overwrite + public LOTRBiomeVariant getBiomeVariantAt(int i, int k) { + short[] variants; + Chunk chunk = this.worldObj.getChunkFromBlockCoords(i, k); + if (chunk != null && + (variants = LOTRBiomeVariantStorageShort.getChunkBiomeVariants(this.worldObj, chunk)) != null) { + if (variants.length == 256) { + int chunkX = i & 0xF; + int chunkZ = k & 0xF; + short variantID = variants[chunkX + chunkZ * 16]; + return LOTRBiomeVariant.getVariantForID(variantID); + } + FMLLog.severe("Found chunk biome variant array of unexpected length " + variants.length); + } + if (!this.worldObj.isRemote) { + return this.getBiomeVariants(null, i, k, 1, 1)[0]; + } + return LOTRBiomeVariant.STANDARD; + } +} diff --git a/src/main/java/com/falsepattern/endlessids/mixin/plugin/Mixin.java b/src/main/java/com/falsepattern/endlessids/mixin/plugin/Mixin.java index 0610876..0c12da4 100644 --- a/src/main/java/com/falsepattern/endlessids/mixin/plugin/Mixin.java +++ b/src/main/java/com/falsepattern/endlessids/mixin/plugin/Mixin.java @@ -121,11 +121,19 @@ public enum Mixin implements IMixin { GalactiCraftChunkProviderOrbitMixin(Side.COMMON, require(TargetedMod.GALACTICRAFTCORE), "galacticraft.ChunkProviderOrbitMixin"), GalactiCraftConfigManagerCoreMixin(Side.COMMON, require(TargetedMod.GALACTICRAFTCORE), - "galacticraft.ConfigManagerCoreMixin"), + "galacticraft.ConfigManagerCoreMixin"), //endregion GalactiCraftCore->common //region ICG->common ICGMysteriumPatchesFixesCaveMixin(Side.COMMON, require(TargetedMod.ICG), "icg.MysteriumPatchesFixesCaveMixin"), //endregion ICG->common + //region LOTR->common + LOTRBiomeVariantStorageMixin(Side.COMMON, require(TargetedMod.LOTR), "lotr.LOTRBiomeVariantStorageMixin"), + LOTRChunkProviderMixin(Side.COMMON, require(TargetedMod.LOTR), "lotr.LOTRChunkProviderMixin"), + LOTRChunkProviderUtumnoMixin(Side.COMMON, require(TargetedMod.LOTR), "lotr.LOTRChunkProviderUtumnoMixin"), + LOTRPacketBiomeVariantsWatchHandlerMixin(Side.COMMON, require(TargetedMod.LOTR), + "lotr.LOTRPacketBiomeVariantsWatchHandlerMixin"), + LOTRWorldChunkManagerMixin(Side.COMMON, require(TargetedMod.LOTR), "lotr.LOTRWorldChunkManagerMixin"), + //endregion LOTR->common //region MFQM->common MFQMMixin(Side.COMMON, require(TargetedMod.MFQM), "mfqm.MFQMMixin"), MFQMDataWatcherMixin(Side.COMMON, require(TargetedMod.MFQM).and(condition(() -> IEConfig.extendDataWatcher)), diff --git a/src/main/java/com/falsepattern/endlessids/mixin/plugin/TargetedMod.java b/src/main/java/com/falsepattern/endlessids/mixin/plugin/TargetedMod.java index dc8aba0..b227ad4 100644 --- a/src/main/java/com/falsepattern/endlessids/mixin/plugin/TargetedMod.java +++ b/src/main/java/com/falsepattern/endlessids/mixin/plugin/TargetedMod.java @@ -26,6 +26,7 @@ public enum TargetedMod implements ITargetedMod { FUTUREPACK("Futurepack", true, startsWith("[1.7.10]futurepack").or(startsWith("futurepack-"))), GALACTICRAFTCORE("GalactiCraftCore", false, startsWith("galacticraftcore")), ICG("Immersive Cavegen", true, startsWith("immersivecavegen")), + LOTR("LOTR Mod", false, startsWith("lotrmod")), MFQM("More Fun Quicksand Mod", false, startsWith("morefunquicksandmod-")), NATURESCOMPASS("Nature's Compass", true, startsWith("naturescompass")), NETHERLICIOUS("Netherlicious", true, startsWith("netherlicious-")),