diff --git a/src/launch/java/baritone/launch/mixins/MixinChunkArray.java b/src/launch/java/baritone/launch/mixins/MixinChunkArray.java new file mode 100644 index 000000000..58ac3418f --- /dev/null +++ b/src/launch/java/baritone/launch/mixins/MixinChunkArray.java @@ -0,0 +1,92 @@ +/* + * This file is part of Baritone. + * + * Baritone 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, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone 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 Baritone. If not, see . + */ + +package baritone.launch.mixins; + +import baritone.utils.accessor.IChunkArray; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.chunk.Chunk; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.concurrent.atomic.AtomicReferenceArray; + +@Mixin(targets = "net.minecraft.client.multiplayer.ClientChunkProvider$ChunkArray") +public abstract class MixinChunkArray implements IChunkArray { + @Shadow + private AtomicReferenceArray chunks; + @Shadow + private int viewDistance; + @Shadow + private int sideLength; + @Shadow + private int centerX; + @Shadow + private int centerZ; + @Shadow + private int loaded; + + @Shadow + protected abstract boolean inView(int x, int z); + + @Shadow + protected abstract int getIndex(int x, int z); + + @Shadow + protected abstract void replace(int index, Chunk chunk); + + @Override + public int centerX() { + return centerX; + } + + @Override + public int centerZ() { + return centerZ; + } + + @Override + public int viewDistance() { + return viewDistance; + } + + @Override + public AtomicReferenceArray getChunks() { + return chunks; + } + + @Override + public void copyFrom(IChunkArray other) { + centerX = other.centerX(); + centerZ = other.centerZ(); + + AtomicReferenceArray copyingFrom = other.getChunks(); + for (int k = 0; k < copyingFrom.length(); ++k) { + Chunk chunk = copyingFrom.get(k); + if (chunk != null) { + ChunkPos chunkpos = chunk.getPos(); + if (inView(chunkpos.x, chunkpos.z)) { + int index = getIndex(chunkpos.x, chunkpos.z); + if (chunks.get(index) != null) { + throw new IllegalStateException("Doing this would mutate the client's REAL loaded chunks?!"); + } + replace(index, chunk); + } + } + } + } +} diff --git a/src/launch/java/baritone/launch/mixins/MixinClientChunkProvider.java b/src/launch/java/baritone/launch/mixins/MixinClientChunkProvider.java new file mode 100644 index 000000000..700f54ae2 --- /dev/null +++ b/src/launch/java/baritone/launch/mixins/MixinClientChunkProvider.java @@ -0,0 +1,61 @@ +/* + * This file is part of Baritone. + * + * Baritone 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, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone 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 Baritone. If not, see . + */ + +package baritone.launch.mixins; + +import baritone.utils.accessor.IChunkArray; +import baritone.utils.accessor.IClientChunkProvider; +import net.minecraft.client.multiplayer.ClientChunkProvider; +import net.minecraft.client.world.ClientWorld; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.lang.reflect.Field; +import java.util.Arrays; + +@Mixin(ClientChunkProvider.class) +public class MixinClientChunkProvider implements IClientChunkProvider { + + @Shadow + private ClientWorld world; + + @Override + public ClientChunkProvider createThreadSafeCopy() { + IChunkArray arr = extractReferenceArray(); + ClientChunkProvider result = new ClientChunkProvider(world, arr.viewDistance() - 3); // -3 because its adds 3 for no reason lmao + IChunkArray copyArr = ((IClientChunkProvider) result).extractReferenceArray(); + copyArr.copyFrom(arr); + if (copyArr.viewDistance() != arr.viewDistance()) { + throw new IllegalStateException(copyArr.viewDistance() + " " + arr.viewDistance()); + } + return result; + } + + @Override + public IChunkArray extractReferenceArray() { + for (Field f : ClientChunkProvider.class.getDeclaredFields()) { + if (IChunkArray.class.isAssignableFrom(f.getType())) { + try { + return (IChunkArray) f.get(this); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } + throw new RuntimeException(Arrays.toString(ClientChunkProvider.class.getDeclaredFields())); + } +} diff --git a/src/launch/resources/mixins.baritone.json b/src/launch/resources/mixins.baritone.json index c908ccafd..1f09b1698 100644 --- a/src/launch/resources/mixins.baritone.json +++ b/src/launch/resources/mixins.baritone.json @@ -9,6 +9,8 @@ }, "client": [ "MixinBlockPos", + "MixinChunkArray", + "MixinClientChunkProvider", "MixinClientPlayerEntity", "MixinClientPlayNetHandler", "MixinEntity", diff --git a/src/main/java/baritone/event/GameEventHandler.java b/src/main/java/baritone/event/GameEventHandler.java index e20a92be4..18f03d956 100644 --- a/src/main/java/baritone/event/GameEventHandler.java +++ b/src/main/java/baritone/event/GameEventHandler.java @@ -51,6 +51,7 @@ public final class GameEventHandler implements IEventBus, Helper { try { baritone.bsi = new BlockStateInterface(baritone.getPlayerContext(), true); } catch (Exception ex) { + ex.printStackTrace(); baritone.bsi = null; } } else { diff --git a/src/main/java/baritone/utils/BlockStateInterface.java b/src/main/java/baritone/utils/BlockStateInterface.java index 7dfd153e3..5fd1a5909 100644 --- a/src/main/java/baritone/utils/BlockStateInterface.java +++ b/src/main/java/baritone/utils/BlockStateInterface.java @@ -21,6 +21,7 @@ import baritone.Baritone; import baritone.api.utils.IPlayerContext; import baritone.cache.CachedRegion; import baritone.cache.WorldData; +import baritone.utils.accessor.IClientChunkProvider; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -59,9 +60,10 @@ public class BlockStateInterface { public BlockStateInterface(World world, WorldData worldData, boolean copyLoadedChunks) { this.worldData = worldData; - this.provider = (ClientChunkProvider) world.getChunkProvider(); - if (copyLoadedChunks) { // todo - System.out.println("Really gotta do this"); + if (copyLoadedChunks) { + this.provider = ((IClientChunkProvider) world.getChunkProvider()).createThreadSafeCopy(); + } else { + this.provider = (ClientChunkProvider) world.getChunkProvider(); } this.useTheRealWorld = !Baritone.settings().pathThroughCachedOnly.value; if (!Minecraft.getInstance().isOnExecutionThread()) { diff --git a/src/main/java/baritone/utils/accessor/IChunkArray.java b/src/main/java/baritone/utils/accessor/IChunkArray.java new file mode 100644 index 000000000..147f64007 --- /dev/null +++ b/src/main/java/baritone/utils/accessor/IChunkArray.java @@ -0,0 +1,34 @@ +/* + * This file is part of Baritone. + * + * Baritone 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, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone 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 Baritone. If not, see . + */ + +package baritone.utils.accessor; + +import net.minecraft.world.chunk.Chunk; + +import java.util.concurrent.atomic.AtomicReferenceArray; + +public interface IChunkArray { + void copyFrom(IChunkArray other); + + AtomicReferenceArray getChunks(); + + int centerX(); + + int centerZ(); + + int viewDistance(); +} diff --git a/src/main/java/baritone/utils/accessor/IClientChunkProvider.java b/src/main/java/baritone/utils/accessor/IClientChunkProvider.java new file mode 100644 index 000000000..cc7483ab4 --- /dev/null +++ b/src/main/java/baritone/utils/accessor/IClientChunkProvider.java @@ -0,0 +1,26 @@ +/* + * This file is part of Baritone. + * + * Baritone 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, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone 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 Baritone. If not, see . + */ + +package baritone.utils.accessor; + +import net.minecraft.client.multiplayer.ClientChunkProvider; + +public interface IClientChunkProvider { + ClientChunkProvider createThreadSafeCopy(); + + IChunkArray extractReferenceArray(); +}