diff --git a/build.gradle.kts b/build.gradle.kts
index 59b52c7..48b204e 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -17,6 +17,7 @@ minecraft_fp {
core {
coreModClass = "asm.EndlessIDsCore"
+ accessTransformerFile = "endlessids_at.cfg"
}
tokens {
diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/biome/galaxyspace/ChunkProviderSpaceLakesGTNHMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/biome/galaxyspace/ChunkProviderSpaceLakesGTNHMixin.java
new file mode 100644
index 0000000..6986df2
--- /dev/null
+++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/biome/galaxyspace/ChunkProviderSpaceLakesGTNHMixin.java
@@ -0,0 +1,63 @@
+/*
+ * EndlessIDs
+ *
+ * Copyright (C) 2022-2025 FalsePattern, The MEGA Team
+ * Copyright (C) 2025 Cardinalstar16
+ * All Rights Reserved
+ *
+ * The above copyright notice, this permission notice and the word "MEGA"
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, only version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.falsepattern.endlessids.mixin.mixins.common.biome.galaxyspace;
+
+import com.falsepattern.endlessids.mixin.helpers.BiomePatchHelper;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Pseudo;
+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;
+import net.minecraft.world.gen.ChunkProviderGenerate;
+
+@Pseudo
+@Mixin(targets = "galaxyspace.core.dimension.ChunkProviderSpaceLakes",
+ remap = false)
+
+public abstract class ChunkProviderSpaceLakesGTNHMixin extends ChunkProviderGenerate
+{
+
+ public ChunkProviderSpaceLakesGTNHMixin(World p_i2006_1_, long p_i2006_2_, boolean p_i2006_4_) {
+ super(p_i2006_1_, p_i2006_2_, p_i2006_4_);
+ }
+
+ /**
+ * @author Cardinalstar16
+ * @reason The Galaxy-space mod maintained by GTNH has a different class layout than
+ * non-GTNH versions of galaxy space. More importantly, biomesForGeneration is AT'd to be protected,
+ * but cannot be shadowed due to the fact that private members aren't in the byte code of the
+ * children classes (from what I understand).
+ */
+ @SuppressWarnings("UnresolvedMixinReference")
+ @Redirect(method = "func_73154_d",
+ at = @At(value = "INVOKE",
+ target = "Lnet/minecraft/world/chunk/Chunk;func_76605_m()[B"),
+ require = 0,
+ expect = 0)
+ private byte[] setBiomesTweaked(Chunk chunk) {
+ return BiomePatchHelper.getBiomeArrayTweaked(chunk, biomesForGeneration);
+ }
+}
diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/BlockFireMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/BlockFireMixin.java
similarity index 99%
rename from src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/BlockFireMixin.java
rename to src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/BlockFireMixin.java
index 75d5215..868428e 100644
--- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/BlockFireMixin.java
+++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/BlockFireMixin.java
@@ -20,7 +20,7 @@
* along with this program. If not, see .
*/
-package com.falsepattern.endlessids.mixin.mixins.common.blockitem.vanilla;
+package com.falsepattern.endlessids.mixin.mixins.common.blockitem.common;
import com.falsepattern.endlessids.constants.ExtendedConstants;
import com.falsepattern.endlessids.constants.VanillaConstants;
diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/BlockMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/BlockMixin.java
similarity index 99%
rename from src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/BlockMixin.java
rename to src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/BlockMixin.java
index e199ea8..f9e4c0e 100644
--- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/BlockMixin.java
+++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/BlockMixin.java
@@ -20,7 +20,7 @@
* along with this program. If not, see .
*/
-package com.falsepattern.endlessids.mixin.mixins.common.blockitem.vanilla;
+package com.falsepattern.endlessids.mixin.mixins.common.blockitem.common;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/ExtendedBlockStorageMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/ExtendedBlockStorageMixin.java
new file mode 100644
index 0000000..2d23efe
--- /dev/null
+++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/ExtendedBlockStorageMixin.java
@@ -0,0 +1,368 @@
+/*
+ * EndlessIDs
+ *
+ * Copyright (C) 2022-2025 FalsePattern, The MEGA Team
+ * All Rights Reserved
+ *
+ * The above copyright notice, this permission notice and the words "MEGA"
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, only version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.falsepattern.endlessids.mixin.mixins.common.blockitem.common;
+
+import com.falsepattern.endlessids.EndlessIDs;
+import com.falsepattern.endlessids.Hooks;
+import com.falsepattern.endlessids.Tags;
+import com.falsepattern.endlessids.config.GeneralConfig;
+import com.falsepattern.endlessids.mixin.helpers.SubChunkBlockHook;
+import lombok.val;
+import lombok.var;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Overwrite;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.Redirect;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+import net.minecraft.block.Block;
+import net.minecraft.init.Blocks;
+import net.minecraft.world.chunk.NibbleArray;
+import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
+
+import static com.falsepattern.endlessids.constants.ExtendedConstants.blocksPerSubChunk;
+
+@Mixin(ExtendedBlockStorage.class)
+public abstract class ExtendedBlockStorageMixin implements SubChunkBlockHook {
+ @Shadow
+ private int blockRefCount;
+ @Shadow
+ private int tickRefCount;
+
+ @Shadow
+ private byte[] blockLSBArray;
+ @Shadow
+ private NibbleArray blockMSBArray;
+ private NibbleArray b2High;
+ private byte[] b3;
+
+ @Shadow
+ private NibbleArray blockMetadataArray;
+ private NibbleArray m1High;
+ private byte[] m2;
+
+ public int eid$getID(int x, int y, int z) {
+ int index = y << 8 | z << 4 | x;
+ int id = blockLSBArray[index] & 0xFF;
+ if (blockMSBArray != null) {
+ id |= blockMSBArray.get(x, y, z) << 8;
+ if (b2High != null) {
+ id |= b2High.get(x, y, z) << 12;
+ if (b3 != null) {
+ id |= (b3[index] & 0xFF) << 16;
+ }
+ }
+ }
+ return id;
+ }
+
+ public void eid$setID(int x, int y, int z, int id) {
+ int index = y << 8 | z << 4 | x;
+ blockLSBArray[index] = (byte) (id & 0xFF);
+ if (id > 0xFF) {
+ if (blockMSBArray == null) {
+ eid$createB2Low();
+ }
+ if (id > 0xFFF) {
+ if (b2High == null) {
+ eid$createB2High();
+ }
+ if (id > 0xFFFF && b3 == null) {
+ eid$createB3();
+ }
+ }
+ }
+ if (blockMSBArray != null) {
+ blockMSBArray.set(x, y, z, (id >>> 8) & 0xF);
+ if (b2High != null) {
+ b2High.set(x, y, z, (id >>> 12) & 0xF);
+ if (b3 != null) {
+ b3[index] = (byte) ((id >>> 16) & 0xFF);
+ }
+ }
+ }
+ }
+
+ /**
+ * @author FalsePattern
+ * @reason Direct port from dumped code
+ */
+ @Overwrite
+ public Block getBlockByExtId(int x, int y, int z) {
+ return Block.getBlockById(eid$getID(x, y, z));
+ }
+
+ /**
+ * @author FalsePattern
+ * @reason Direct port from dumped code
+ */
+ @Overwrite
+ public void func_150818_a(int x, int y, int z, Block newBlock) {
+ Block oldBlock = this.getBlockByExtId(x, y, z);
+ if (oldBlock != Blocks.air) {
+ --this.blockRefCount;
+ if (oldBlock.getTickRandomly()) {
+ --this.tickRefCount;
+ }
+ }
+
+ if (newBlock != Blocks.air) {
+ ++this.blockRefCount;
+ if (newBlock.getTickRandomly()) {
+ ++this.tickRefCount;
+ }
+ }
+
+ int blockID = Hooks.getIdFromBlockWithCheck(newBlock, oldBlock);
+ eid$setID(x, y, z, blockID);
+ }
+
+ /**
+ * @author FalsePattern
+ * @reason meta ID extension
+ */
+ @Overwrite
+ public int getExtBlockMetadata(int x, int y, int z) {
+ int meta = blockMetadataArray.get(x, y, z);
+ if (m1High != null) {
+ meta |= m1High.get(x, y, z) << 4;
+ if (m2 != null) {
+ meta |= (m2[(y << 8) | (z << 4) | x] & 0xFF) << 8;
+ }
+ }
+ return meta;
+ }
+
+ /**
+ * @author FalsePattern
+ * @reason meta ID extension
+ */
+ @Overwrite
+ public void setExtBlockMetadata(int x, int y, int z, int meta) {
+ blockMetadataArray.set(x, y, z, meta & 0xF);
+ if (meta > 0xF) {
+ if (m1High == null) {
+ eid$createM1High();
+ }
+ if (meta > 0xFF && m2 == null) {
+ eid$createM2();
+ }
+ }
+ if (m1High != null) {
+ m1High.set(x, y, z, (meta >>> 4) & 0xF);
+ if (m2 != null) {
+ m2[(y << 8) | (z << 4) | x] = (byte) ((meta >>> 8) & 0xFF);
+ }
+ }
+ }
+
+ @Override
+ public int eid$getMetadata(int x, int y, int z) {
+ return getExtBlockMetadata(x, y, z);
+ }
+
+ @Override
+ public void eid$setMetadata(int x, int y, int z, int id) {
+ setExtBlockMetadata(x, y, z, id);
+ }
+
+ private UnsupportedOperationException emergencyCrash() {
+ val crashMSG = "A mod that is incompatible with " + Tags.MODNAME + " has tried to access the block array of a" +
+ " chunk like in vanilla! Crashing in fear of potential world corruption!\n" +
+ "Please report this issue on https://github.com/GTMEGA/EndlessIDs ASAP!";
+ EndlessIDs.LOG.fatal(crashMSG);
+ return new UnsupportedOperationException(crashMSG);
+ }
+
+ @Override
+ public byte[] eid$getB1() {
+ return blockLSBArray;
+ }
+
+ @Override
+ public void eid$setB1(byte[] data) {
+ blockLSBArray = data;
+ }
+
+ @Override
+ public NibbleArray eid$getB2Low() {
+ return blockMSBArray;
+ }
+
+ @Override
+ public void eid$setB2Low(NibbleArray data) {
+ blockMSBArray = data;
+ }
+
+ @Override
+ public NibbleArray eid$createB2Low() {
+ return (blockMSBArray = new NibbleArray(blocksPerSubChunk, 4));
+ }
+
+ @Override
+ public NibbleArray eid$getB2High() {
+ return b2High;
+ }
+
+ @Override
+ public void eid$setB2High(NibbleArray data) {
+ b2High = data;
+ }
+
+ @Override
+ public NibbleArray eid$createB2High() {
+ return (b2High = new NibbleArray(blocksPerSubChunk, 4));
+ }
+
+ @Override
+ public byte[] eid$getB3() {
+ return b3;
+ }
+
+ @Override
+ public void eid$setB3(byte[] data) {
+ b3 = data;
+ }
+
+ @Override
+ public byte[] eid$createB3() {
+ return b3 = new byte[blocksPerSubChunk];
+ }
+
+ @Override
+ public NibbleArray eid$getM1Low() {
+ return blockMetadataArray;
+ }
+
+ @Override
+ public void eid$setM1Low(NibbleArray m1Low) {
+ blockMetadataArray = m1Low;
+ }
+
+ @Override
+ public NibbleArray eid$getM1High() {
+ return m1High;
+ }
+
+ @Override
+ public void eid$setM1High(NibbleArray m1High) {
+ this.m1High = m1High;
+ }
+
+ @Override
+ public NibbleArray eid$createM1High() {
+ return (m1High = new NibbleArray(blocksPerSubChunk, 4));
+ }
+
+ @Override
+ public byte[] eid$getM2() {
+ return m2;
+ }
+
+ @Override
+ public void eid$setM2(byte[] m2) {
+ this.m2 = m2;
+ }
+
+ @Override
+ public byte[] eid$createM2() {
+ return (m2 = new byte[blocksPerSubChunk]);
+ }
+
+ @Override
+ public int eid$getBlockMask() {
+ if (blockMSBArray == null) {
+ return 0b00;
+ }
+ if (b2High == null) {
+ return 0b01;
+ }
+ if (b3 == null) {
+ return 0b10;
+ }
+ return 0b11;
+ }
+
+ @Override
+ public int eid$getMetadataMask() {
+ if (m1High == null) {
+ return 0b01;
+ }
+ if (m2 == null) {
+ return 0b10;
+ }
+ return 0b11;
+ }
+
+ @Inject(method = {"getBlockMSBArray", "createBlockMSBArray"},
+ at = @At("HEAD"),
+ expect = 0)
+ private void crashMSBArray(CallbackInfoReturnable cir) {
+ throw emergencyCrash();
+ }
+
+ @Inject(method = "clearMSBArray",
+ at = @At("HEAD"),
+ expect = 0)
+ private void crashMSBArray(CallbackInfo ci) {
+ throw emergencyCrash();
+ }
+
+ @Inject(method = "setBlockMSBArray",
+ at = @At("HEAD"),
+ expect = 0)
+ private void crashMSBArray(NibbleArray p_76673_1_, CallbackInfo ci) {
+ throw emergencyCrash();
+ }
+
+ @Inject(method = "setBlockLSBArray",
+ at = @At("HEAD"),
+ expect = 0)
+ private void crashLSBArray(byte[] p_76664_1_, CallbackInfo ci) {
+ throw emergencyCrash();
+ }
+
+ @Inject(method = "getBlockLSBArray",
+ at = @At("HEAD"),
+ expect = 0)
+ private void crashLSBArray(CallbackInfoReturnable cir) {
+ throw emergencyCrash();
+ }
+
+ @Inject(method = "setBlockMetadataArray",
+ at = @At("HEAD"),
+ expect = 0)
+ private void crashMetadataArray(NibbleArray p_76668_1_, CallbackInfo ci) {
+ throw emergencyCrash();
+ }
+
+ @Inject(method = "getMetadataArray",
+ at = @At("HEAD"),
+ expect = 0)
+ private void crashMetadataArray(CallbackInfoReturnable cir) {
+ throw emergencyCrash();
+ }
+}
diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/ItemInWorldManagerMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/ItemInWorldManagerMixin.java
similarity index 99%
rename from src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/ItemInWorldManagerMixin.java
rename to src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/ItemInWorldManagerMixin.java
index daf8092..4b2425f 100644
--- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/ItemInWorldManagerMixin.java
+++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/ItemInWorldManagerMixin.java
@@ -20,7 +20,7 @@
* along with this program. If not, see .
*/
-package com.falsepattern.endlessids.mixin.mixins.common.blockitem.vanilla;
+package com.falsepattern.endlessids.mixin.mixins.common.blockitem.common;
import com.falsepattern.endlessids.constants.ExtendedConstants;
import com.falsepattern.endlessids.constants.VanillaConstants;
diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/ItemStackMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/ItemStackMixin.java
similarity index 97%
rename from src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/ItemStackMixin.java
rename to src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/ItemStackMixin.java
index e806f8e..d50d7b5 100644
--- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/ItemStackMixin.java
+++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/ItemStackMixin.java
@@ -20,9 +20,8 @@
* along with this program. If not, see .
*/
-package com.falsepattern.endlessids.mixin.mixins.common.blockitem.vanilla;
+package com.falsepattern.endlessids.mixin.mixins.common.blockitem.common;
-import com.falsepattern.endlessids.constants.VanillaConstants;
import com.falsepattern.endlessids.util.DataUtil;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/PacketBufferMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/PacketBufferMixin.java
similarity index 99%
rename from src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/PacketBufferMixin.java
rename to src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/PacketBufferMixin.java
index 50ca213..dbc0758 100644
--- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/PacketBufferMixin.java
+++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/PacketBufferMixin.java
@@ -20,7 +20,7 @@
* along with this program. If not, see .
*/
-package com.falsepattern.endlessids.mixin.mixins.common.blockitem.vanilla;
+package com.falsepattern.endlessids.mixin.mixins.common.blockitem.common;
import io.netty.buffer.ByteBuf;
import org.spongepowered.asm.mixin.Mixin;
diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/S22PacketMultiBlockChangeMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/S22PacketMultiBlockChangeMixin.java
similarity index 99%
rename from src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/S22PacketMultiBlockChangeMixin.java
rename to src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/S22PacketMultiBlockChangeMixin.java
index 023ed94..184e91b 100644
--- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/S22PacketMultiBlockChangeMixin.java
+++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/S22PacketMultiBlockChangeMixin.java
@@ -20,7 +20,7 @@
* along with this program. If not, see .
*/
-package com.falsepattern.endlessids.mixin.mixins.common.blockitem.vanilla;
+package com.falsepattern.endlessids.mixin.mixins.common.blockitem.common;
import com.falsepattern.endlessids.constants.ExtendedConstants;
import com.falsepattern.endlessids.constants.VanillaConstants;
diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/S24PacketBlockActionMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/S24PacketBlockActionMixin.java
similarity index 99%
rename from src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/S24PacketBlockActionMixin.java
rename to src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/S24PacketBlockActionMixin.java
index 6a63749..757a011 100644
--- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/S24PacketBlockActionMixin.java
+++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/S24PacketBlockActionMixin.java
@@ -20,7 +20,7 @@
* along with this program. If not, see .
*/
-package com.falsepattern.endlessids.mixin.mixins.common.blockitem.vanilla;
+package com.falsepattern.endlessids.mixin.mixins.common.blockitem.common;
import com.falsepattern.endlessids.constants.ExtendedConstants;
import com.falsepattern.endlessids.constants.VanillaConstants;
diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/StatListMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/StatListMixin.java
similarity index 99%
rename from src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/StatListMixin.java
rename to src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/StatListMixin.java
index b84c93d..10d8802 100644
--- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/StatListMixin.java
+++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/StatListMixin.java
@@ -20,7 +20,7 @@
* along with this program. If not, see .
*/
-package com.falsepattern.endlessids.mixin.mixins.common.blockitem.vanilla;
+package com.falsepattern.endlessids.mixin.mixins.common.blockitem.common;
import com.falsepattern.endlessids.constants.ExtendedConstants;
import com.falsepattern.endlessids.constants.VanillaConstants;
diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/WorldMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/WorldMixin.java
similarity index 99%
rename from src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/WorldMixin.java
rename to src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/WorldMixin.java
index 18444b9..edc2be7 100644
--- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/WorldMixin.java
+++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/common/WorldMixin.java
@@ -20,7 +20,7 @@
* along with this program. If not, see .
*/
-package com.falsepattern.endlessids.mixin.mixins.common.blockitem.vanilla;
+package com.falsepattern.endlessids.mixin.mixins.common.blockitem.common;
import com.falsepattern.endlessids.constants.ExtendedConstants;
import com.falsepattern.endlessids.constants.VanillaConstants;
diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/thermos/NibbleArrayMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/thermos/NibbleArrayMixin.java
new file mode 100644
index 0000000..984c717
--- /dev/null
+++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/thermos/NibbleArrayMixin.java
@@ -0,0 +1,86 @@
+/*
+ * EndlessIDs
+ *
+ * Copyright (C) 2022-2025 FalsePattern, The MEGA Team
+ * Copyright (C) 2025 Cardinalstar16
+ * All Rights Reserved
+ *
+ * The above copyright notice, this permission notice and the word "MEGA"
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, only version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.falsepattern.endlessids.mixin.mixins.common.blockitem.thermos;
+
+import org.spongepowered.asm.lib.Opcodes;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import net.minecraft.world.chunk.NibbleArray;
+
+@Mixin(NibbleArray.class)
+public class NibbleArrayMixin {
+
+ @Shadow
+ public byte[] data; // Thermos renamed 'data'
+ @Shadow private int depthBits; // depthBits
+ @Shadow private int depthBitsPlusFour; // depthBitsPlusFour
+
+ @SuppressWarnings("MixinAnnotationTarget")
+ @Shadow private int length;
+ @SuppressWarnings("MixinAnnotationTarget")
+ @Shadow private byte trivialByte;
+ @SuppressWarnings("MixinAnnotationTarget")
+ @Shadow private byte trivialValue;
+
+ /**
+ * @author Cardinalstar16
+ * @reason Thermos compat.
+ * Thermos thinks it's a good idea to nullify some nibble array members if they are a
+ * "Trivial array". Just disable this functionality if we detect thermos.
+ */
+ @SuppressWarnings("MixinAnnotationTarget")
+ @Inject(
+ method = "detectAndProcessTrivialArray",
+ at = @At(
+ value = "FIELD",
+ opcode = Opcodes.PUTFIELD,
+ target = "Lnet/minecraft/world/chunk/NibbleArray;data:[B",
+ shift = At.Shift.BEFORE
+ ),
+ cancellable = true)
+ private void logBeforeNull(CallbackInfo ci) {
+ ci.cancel();
+ }
+
+ /**
+ * @author Cardinalstar16
+ * @reason Thermos compat.
+ * Thermos thinks it's a good idea to nullify some nibble array members if they are a
+ * "Trivial array". Just disable this functionality if we detect thermos.
+ */
+ @Inject(method = "(II)V", at = @At("RETURN"))
+ private void fixConstructor(int par1, int par2, CallbackInfo ci) {
+ this.data = new byte[par1 >> 1];
+ this.depthBits = par2;
+ this.depthBitsPlusFour = par2 + 4;
+ this.length = par1 >> 1;
+ this.trivialValue = 0;
+ this.trivialByte = 0;
+ }
+
+}
diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/ExtendedBlockStorageMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/ExtendedBlockStorageMixin.java
index e7906de..8ccddad 100644
--- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/ExtendedBlockStorageMixin.java
+++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/ExtendedBlockStorageMixin.java
@@ -22,173 +22,25 @@
package com.falsepattern.endlessids.mixin.mixins.common.blockitem.vanilla;
-import com.falsepattern.endlessids.EndlessIDs;
-import com.falsepattern.endlessids.Hooks;
-import com.falsepattern.endlessids.Tags;
import com.falsepattern.endlessids.config.GeneralConfig;
-import com.falsepattern.endlessids.mixin.helpers.SubChunkBlockHook;
-import lombok.val;
import lombok.var;
import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.Overwrite;
-import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
-import net.minecraft.world.chunk.NibbleArray;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
-import static com.falsepattern.endlessids.constants.ExtendedConstants.blocksPerSubChunk;
-
@Mixin(ExtendedBlockStorage.class)
-public abstract class ExtendedBlockStorageMixin implements SubChunkBlockHook {
- @Shadow
- private int blockRefCount;
- @Shadow
- private int tickRefCount;
-
- @Shadow
- private byte[] blockLSBArray;
- @Shadow
- private NibbleArray blockMSBArray;
- private NibbleArray b2High;
- private byte[] b3;
-
- @Shadow
- private NibbleArray blockMetadataArray;
- private NibbleArray m1High;
- private byte[] m2;
-
- public int eid$getID(int x, int y, int z) {
- int index = y << 8 | z << 4 | x;
- int id = blockLSBArray[index] & 0xFF;
- if (blockMSBArray != null) {
- id |= blockMSBArray.get(x, y, z) << 8;
- if (b2High != null) {
- id |= b2High.get(x, y, z) << 12;
- if (b3 != null) {
- id |= (b3[index] & 0xFF) << 16;
- }
- }
- }
- return id;
- }
-
- public void eid$setID(int x, int y, int z, int id) {
- int index = y << 8 | z << 4 | x;
- blockLSBArray[index] = (byte) (id & 0xFF);
- if (id > 0xFF) {
- if (blockMSBArray == null) {
- eid$createB2Low();
- }
- if (id > 0xFFF) {
- if (b2High == null) {
- eid$createB2High();
- }
- if (id > 0xFFFF && b3 == null) {
- eid$createB3();
- }
- }
- }
- if (blockMSBArray != null) {
- blockMSBArray.set(x, y, z, (id >>> 8) & 0xF);
- if (b2High != null) {
- b2High.set(x, y, z, (id >>> 12) & 0xF);
- if (b3 != null) {
- b3[index] = (byte) ((id >>> 16) & 0xFF);
- }
- }
- }
- }
-
- /**
- * @author FalsePattern
- * @reason Direct port from dumped code
- */
- @Overwrite
- public Block getBlockByExtId(int x, int y, int z) {
- return Block.getBlockById(eid$getID(x, y, z));
- }
-
- /**
- * @author FalsePattern
- * @reason Direct port from dumped code
- */
- @Overwrite
- public void func_150818_a(int x, int y, int z, Block newBlock) {
- Block oldBlock = this.getBlockByExtId(x, y, z);
- if (oldBlock != Blocks.air) {
- --this.blockRefCount;
- if (oldBlock.getTickRandomly()) {
- --this.tickRefCount;
- }
- }
-
- if (newBlock != Blocks.air) {
- ++this.blockRefCount;
- if (newBlock.getTickRandomly()) {
- ++this.tickRefCount;
- }
- }
-
- int blockID = Hooks.getIdFromBlockWithCheck(newBlock, oldBlock);
- eid$setID(x, y, z, blockID);
- }
-
- /**
- * @author FalsePattern
- * @reason meta ID extension
- */
- @Overwrite
- public int getExtBlockMetadata(int x, int y, int z) {
- int meta = blockMetadataArray.get(x, y, z);
- if (m1High != null) {
- meta |= m1High.get(x, y, z) << 4;
- if (m2 != null) {
- meta |= (m2[(y << 8) | (z << 4) | x] & 0xFF) << 8;
- }
- }
- return meta;
- }
-
+public class ExtendedBlockStorageMixin
+{
/**
- * @author FalsePattern
- * @reason meta ID extension
+ * @author Cardinalstar16
+ * @reason Id Extension
+ * Thermos does this already, so I just moved this into a mixin that is only loaded if thermos
+ * is not enabled.
*/
- @Overwrite
- public void setExtBlockMetadata(int x, int y, int z, int meta) {
- blockMetadataArray.set(x, y, z, meta & 0xF);
- if (meta > 0xF) {
- if (m1High == null) {
- eid$createM1High();
- }
- if (meta > 0xFF && m2 == null) {
- eid$createM2();
- }
- }
- if (m1High != null) {
- m1High.set(x, y, z, (meta >>> 4) & 0xF);
- if (m2 != null) {
- m2[(y << 8) | (z << 4) | x] = (byte) ((meta >>> 8) & 0xFF);
- }
- }
- }
-
- @Override
- public int eid$getMetadata(int x, int y, int z) {
- return getExtBlockMetadata(x, y, z);
- }
-
- @Override
- public void eid$setMetadata(int x, int y, int z, int id) {
- setExtBlockMetadata(x, y, z, id);
- }
-
@Redirect(method = "removeInvalidBlocks",
at = @At(value = "INVOKE",
target = "Lnet/minecraft/world/chunk/storage/ExtendedBlockStorage;getBlockByExtId(III)Lnet/minecraft/block/Block;"),
@@ -201,181 +53,4 @@ private Block removeInvalidBlocks(ExtendedBlockStorage instance, int x, int y, i
}
return block;
}
-
- private UnsupportedOperationException emergencyCrash() {
- val crashMSG = "A mod that is incompatible with " + Tags.MODNAME + " has tried to access the block array of a" +
- " chunk like in vanilla! Crashing in fear of potential world corruption!\n" +
- "Please report this issue on https://github.com/GTMEGA/EndlessIDs ASAP!";
- EndlessIDs.LOG.fatal(crashMSG);
- return new UnsupportedOperationException(crashMSG);
- }
-
- @Override
- public byte[] eid$getB1() {
- return blockLSBArray;
- }
-
- @Override
- public void eid$setB1(byte[] data) {
- blockLSBArray = data;
- }
-
- @Override
- public NibbleArray eid$getB2Low() {
- return blockMSBArray;
- }
-
- @Override
- public void eid$setB2Low(NibbleArray data) {
- blockMSBArray = data;
- }
-
- @Override
- public NibbleArray eid$createB2Low() {
- return (blockMSBArray = new NibbleArray(blocksPerSubChunk, 4));
- }
-
- @Override
- public NibbleArray eid$getB2High() {
- return b2High;
- }
-
- @Override
- public void eid$setB2High(NibbleArray data) {
- b2High = data;
- }
-
- @Override
- public NibbleArray eid$createB2High() {
- return (b2High = new NibbleArray(blocksPerSubChunk, 4));
- }
-
- @Override
- public byte[] eid$getB3() {
- return b3;
- }
-
- @Override
- public void eid$setB3(byte[] data) {
- b3 = data;
- }
-
- @Override
- public byte[] eid$createB3() {
- return b3 = new byte[blocksPerSubChunk];
- }
-
- @Override
- public NibbleArray eid$getM1Low() {
- return blockMetadataArray;
- }
-
- @Override
- public void eid$setM1Low(NibbleArray m1Low) {
- blockMetadataArray = m1Low;
- }
-
- @Override
- public NibbleArray eid$getM1High() {
- return m1High;
- }
-
- @Override
- public void eid$setM1High(NibbleArray m1High) {
- this.m1High = m1High;
- }
-
- @Override
- public NibbleArray eid$createM1High() {
- return (m1High = new NibbleArray(blocksPerSubChunk, 4));
- }
-
- @Override
- public byte[] eid$getM2() {
- return m2;
- }
-
- @Override
- public void eid$setM2(byte[] m2) {
- this.m2 = m2;
- }
-
- @Override
- public byte[] eid$createM2() {
- return (m2 = new byte[blocksPerSubChunk]);
- }
-
- @Override
- public int eid$getBlockMask() {
- if (blockMSBArray == null) {
- return 0b00;
- }
- if (b2High == null) {
- return 0b01;
- }
- if (b3 == null) {
- return 0b10;
- }
- return 0b11;
- }
-
- @Override
- public int eid$getMetadataMask() {
- if (m1High == null) {
- return 0b01;
- }
- if (m2 == null) {
- return 0b10;
- }
- return 0b11;
- }
-
- @Inject(method = {"getBlockMSBArray", "createBlockMSBArray"},
- at = @At("HEAD"),
- expect = 0)
- private void crashMSBArray(CallbackInfoReturnable cir) {
- throw emergencyCrash();
- }
-
- @Inject(method = "clearMSBArray",
- at = @At("HEAD"),
- expect = 0)
- private void crashMSBArray(CallbackInfo ci) {
- throw emergencyCrash();
- }
-
- @Inject(method = "setBlockMSBArray",
- at = @At("HEAD"),
- expect = 0)
- private void crashMSBArray(NibbleArray p_76673_1_, CallbackInfo ci) {
- throw emergencyCrash();
- }
-
- @Inject(method = "setBlockLSBArray",
- at = @At("HEAD"),
- expect = 0)
- private void crashLSBArray(byte[] p_76664_1_, CallbackInfo ci) {
- throw emergencyCrash();
- }
-
- @Inject(method = "getBlockLSBArray",
- at = @At("HEAD"),
- expect = 0)
- private void crashLSBArray(CallbackInfoReturnable cir) {
- throw emergencyCrash();
- }
-
- @Inject(method = "setBlockMetadataArray",
- at = @At("HEAD"),
- expect = 0)
- private void crashMetadataArray(NibbleArray p_76668_1_, CallbackInfo ci) {
- throw emergencyCrash();
- }
-
- @Inject(method = "getMetadataArray",
- at = @At("HEAD"),
- expect = 0)
- private void crashMetadataArray(CallbackInfoReturnable cir) {
- throw emergencyCrash();
- }
}
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 af06951..179d6a4 100644
--- a/src/main/java/com/falsepattern/endlessids/mixin/plugin/Mixin.java
+++ b/src/main/java/com/falsepattern/endlessids/mixin/plugin/Mixin.java
@@ -277,12 +277,13 @@ public enum Mixin implements IMixins {
common("biome.galacticraft.ChunkProviderOrbitMixin",
"biome.galacticraft.ConfigManagerCoreMixin")),
- Biome_GalaxySpace(Phase.EARLY,
+ Biome_GalaxySpace(Phase.LATE,
Ext.Biome,
require(GalaxySpace),
common("biome.galaxyspace.ChunkProviderKuiperMixin",
"biome.galaxyspace.ChunkProviderMarsSSMixin",
"biome.galaxyspace.ChunkProviderSpaceLakesMixin",
+ "biome.galaxyspace.ChunkProviderSpaceLakesGTNHMixin",
"biome.galaxyspace.ChunkProviderVenusSSMixin")),
Biome_Highlands(Phase.LATE,
@@ -418,19 +419,26 @@ public enum Mixin implements IMixins {
// endregion Biome
// region BlockItem
-
+
BlockItem_Vanilla(Phase.EARLY,
+ () -> { return Ext.BlockItem.getAsBoolean() && !hasThermos(); },
+ common("blockitem.vanilla.ExtendedBlockStorageMixin")),
+ BlockItem_Thermos(Phase.EARLY,
+ () -> { return Ext.BlockItem.getAsBoolean() && hasThermos(); },
+ common("blockitem.thermos.NibbleArrayMixin")),
+
+ BlockItem_Common(Phase.EARLY,
Ext.BlockItem,
- common("blockitem.vanilla.BlockFireMixin",
- "blockitem.vanilla.BlockMixin",
- "blockitem.vanilla.ExtendedBlockStorageMixin",
- "blockitem.vanilla.ItemInWorldManagerMixin",
- "blockitem.vanilla.ItemStackMixin",
- "blockitem.vanilla.PacketBufferMixin",
- "blockitem.vanilla.S22PacketMultiBlockChangeMixin",
- "blockitem.vanilla.S24PacketBlockActionMixin",
- "blockitem.vanilla.StatListMixin",
- "blockitem.vanilla.WorldMixin"),
+ common("blockitem.common.BlockFireMixin",
+ "blockitem.common.BlockMixin",
+ "blockitem.common.ExtendedBlockStorageMixin",
+ "blockitem.common.ItemInWorldManagerMixin",
+ "blockitem.common.ItemStackMixin",
+ "blockitem.common.PacketBufferMixin",
+ "blockitem.common.S22PacketMultiBlockChangeMixin",
+ "blockitem.common.S24PacketBlockActionMixin",
+ "blockitem.common.StatListMixin",
+ "blockitem.common.WorldMixin"),
client("blockitem.vanilla.PlayerControllerMPMixin",
"blockitem.vanilla.RenderGlobalMixin")),
@@ -607,4 +615,16 @@ private static class Ext {
public static final BooleanSupplier Potion = () -> GeneralConfig.extendPotion;
public static final BooleanSupplier Entity = () -> GeneralConfig.extendEntity;
}
+
+ static boolean hasThermos()
+ {
+ try
+ {
+ Class.forName("thermos.Thermos");
+ return true;
+ }
+ catch(ClassNotFoundException ignored) {
+ return false;
+ }
+ }
}
diff --git a/src/main/resources/META-INF/endlessids_at.cfg b/src/main/resources/META-INF/endlessids_at.cfg
new file mode 100644
index 0000000..06e2d10
--- /dev/null
+++ b/src/main/resources/META-INF/endlessids_at.cfg
@@ -0,0 +1,2 @@
+#Fields
+protected net.minecraft.world.gen.ChunkProviderGenerate field_73231_z # biomesForGeneration
\ No newline at end of file