From 60c6d20cc5beb6c9ff67eab367fe60310dcd1637 Mon Sep 17 00:00:00 2001 From: misterx Date: Sun, 30 Jan 2022 01:02:59 +0100 Subject: [PATCH] oresim --- .../anticope/rejects/MeteorRejectsAddon.java | 1 + .../rejects/events/ChunkPosDataEvent.java | 21 + .../rejects/events/SeedChangedEvent.java | 12 + .../mixin/ClientPlayNetworkHandlerMixin.java | 20 + .../java/anticope/rejects/modules/Ore.java | 222 ++++++++ .../java/anticope/rejects/modules/OreSim.java | 477 ++++++++++++++++++ .../anticope/rejects/utils/seeds/Seeds.java | 5 +- src/main/resources/meteor-rejects.mixins.json | 1 + 8 files changed, 758 insertions(+), 1 deletion(-) create mode 100644 src/main/java/anticope/rejects/events/ChunkPosDataEvent.java create mode 100644 src/main/java/anticope/rejects/events/SeedChangedEvent.java create mode 100644 src/main/java/anticope/rejects/mixin/ClientPlayNetworkHandlerMixin.java create mode 100755 src/main/java/anticope/rejects/modules/Ore.java create mode 100755 src/main/java/anticope/rejects/modules/OreSim.java diff --git a/src/main/java/anticope/rejects/MeteorRejectsAddon.java b/src/main/java/anticope/rejects/MeteorRejectsAddon.java index d32ffb4..2148242 100644 --- a/src/main/java/anticope/rejects/MeteorRejectsAddon.java +++ b/src/main/java/anticope/rejects/MeteorRejectsAddon.java @@ -62,6 +62,7 @@ public class MeteorRejectsAddon extends MeteorAddon { modules.add(new Lavacast()); modules.add(new NewChunks()); modules.add(new ObsidianFarm()); + modules.add(new OreSim()); modules.add(new PacketFly()); modules.add(new Painter()); modules.add(new Prone()); diff --git a/src/main/java/anticope/rejects/events/ChunkPosDataEvent.java b/src/main/java/anticope/rejects/events/ChunkPosDataEvent.java new file mode 100644 index 0000000..983790e --- /dev/null +++ b/src/main/java/anticope/rejects/events/ChunkPosDataEvent.java @@ -0,0 +1,21 @@ +package anticope.rejects.events; + +import meteordevelopment.meteorclient.utils.misc.Pool; + +public class ChunkPosDataEvent { + private static final Pool INSTANCE = new Pool<>(ChunkPosDataEvent::new); + + public int chunkX; + public int chunkZ; + + public static ChunkPosDataEvent get(int x, int z) { + ChunkPosDataEvent event = INSTANCE.get(); + event.chunkX = x; + event.chunkZ = z; + return event; + } + + public static void returnChunkDataEvent(ChunkPosDataEvent event) { + INSTANCE.free(event); + } +} \ No newline at end of file diff --git a/src/main/java/anticope/rejects/events/SeedChangedEvent.java b/src/main/java/anticope/rejects/events/SeedChangedEvent.java new file mode 100644 index 0000000..e3293f1 --- /dev/null +++ b/src/main/java/anticope/rejects/events/SeedChangedEvent.java @@ -0,0 +1,12 @@ +package anticope.rejects.events; + +public class SeedChangedEvent { + private static final SeedChangedEvent INSTANCE = new SeedChangedEvent(); + + public Long seed; + + public static SeedChangedEvent get(long seed) { + INSTANCE.seed = seed; + return INSTANCE; + } +} diff --git a/src/main/java/anticope/rejects/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/anticope/rejects/mixin/ClientPlayNetworkHandlerMixin.java new file mode 100644 index 0000000..c8219b5 --- /dev/null +++ b/src/main/java/anticope/rejects/mixin/ClientPlayNetworkHandlerMixin.java @@ -0,0 +1,20 @@ +package anticope.rejects.mixin; + +import anticope.rejects.events.ChunkPosDataEvent; +import meteordevelopment.meteorclient.MeteorClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.packet.s2c.play.ChunkDataS2CPacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientPlayNetworkHandler.class) +public class ClientPlayNetworkHandlerMixin { + + //the normal onChunkDataEvent should just provide coords aswell + @Inject(method = "onChunkData", at = @At("TAIL")) + public void onChunkData(ChunkDataS2CPacket packet, CallbackInfo ci) { + MeteorClient.EVENT_BUS.post(ChunkPosDataEvent.get(packet.getX(), packet.getZ())); + } +} diff --git a/src/main/java/anticope/rejects/modules/Ore.java b/src/main/java/anticope/rejects/modules/Ore.java new file mode 100755 index 0000000..61179a5 --- /dev/null +++ b/src/main/java/anticope/rejects/modules/Ore.java @@ -0,0 +1,222 @@ +package anticope.rejects.modules; + +import meteordevelopment.meteorclient.settings.BoolSetting; +import meteordevelopment.meteorclient.settings.Setting; +import meteordevelopment.meteorclient.utils.render.color.Color; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.intprovider.ConstantIntProvider; +import net.minecraft.util.math.intprovider.IntProvider; +import net.minecraft.util.math.intprovider.UniformIntProvider; +import net.minecraft.world.dimension.DimensionType; + +import java.util.List; +import java.util.*; + +public class Ore { + + private static final Setting coal = new BoolSetting.Builder().name("Coal").build(); + private static final Setting iron = new BoolSetting.Builder().name("Iron").build(); + private static final Setting gold = new BoolSetting.Builder().name("Gold").build(); + private static final Setting redstone = new BoolSetting.Builder().name("Redstone").build(); + private static final Setting diamond = new BoolSetting.Builder().name("Diamond").build(); + private static final Setting lapis = new BoolSetting.Builder().name("Lapis").build(); + private static final Setting copper = new BoolSetting.Builder().name("Kappa").build(); + private static final Setting emerald = new BoolSetting.Builder().name("Emerald").build(); + private static final Setting quartz = new BoolSetting.Builder().name("Quartz").build(); + private static final Setting debris = new BoolSetting.Builder().name("Ancient Debris").build(); + public static final List> oreSettings = new ArrayList<>(Arrays.asList(coal, iron, gold, redstone, diamond, lapis, copper, emerald, quartz, debris)); + public final Type type; + public final Identifier dimension; + public final Map index; + public final boolean depthAverage; + public final Generator generator; + public final int size; + public final Setting enabled; + public final Color color; + public int step; + public IntProvider count; + public int minY; + public int maxY; + public float discardOnAir; + public float chance; + + Ore(Type type, Identifier dimension, Map index, int step, IntProvider count, float chance, boolean depthAverage, int minY, int maxY, Generator generator, int size, float discardOnAir, Setting enabled, Color color) { + this.type = type; + this.dimension = dimension; + this.index = index; + this.step = step; + this.count = count; + this.depthAverage = depthAverage; + this.minY = minY; + this.maxY = maxY; + this.generator = generator; + this.size = size; + this.enabled = enabled; + this.color = color; + this.discardOnAir = discardOnAir; + this.chance = chance; + } + + Ore(Type type, Identifier dimension, int index, int step, IntProvider count, float chance, boolean depthAverage, int minY, int maxY, Generator generator, int size, float discardOnAir, Setting enabled, Color color) { + this(type, dimension, indexToMap(index), step, count, chance, depthAverage, minY, maxY, generator, size, discardOnAir, enabled, color); + } + + Ore(Type type, Identifier dimension, int index, int step, IntProvider count, boolean depthAverage, int minY, int maxY, + @SuppressWarnings("SameParameterValue") Generator generator, int size, Setting enabled, Color color) { + this(type, dimension, indexToMap(index), step, count, 1F, depthAverage, minY, maxY, generator, size, 0F, enabled, color); + } + + Ore(Type type, Identifier dimension, Map index, int step, IntProvider count, boolean depthAverage, int minY, int maxY, + @SuppressWarnings("SameParameterValue") Generator generator, int size, Setting enabled, Color color) { + this(type, dimension, index, step, count, 1F, depthAverage, minY, maxY, generator, size, 0F, enabled, color); + } + + private static HashMap indexToMap(int index) { + HashMap map = new HashMap<>(); + map.put("default", index); + return map; + } + + private static List V1_18() { + List ores = new ArrayList<>(); + + HashMap extraGoldIndex = new HashMap<>(); + extraGoldIndex.put("default", -1); + String[] extraGoldBiomes = new String[]{"badlands", "eroded_badlands", "wooded_badlands"}; + for (String extraGoldBiome : extraGoldBiomes) { + extraGoldIndex.put(extraGoldBiome, 27); + } + + HashMap emeraldIndex = new HashMap<>(); + emeraldIndex.put("default", -1); + String[] emeraldBiomes = new String[]{"windswept_hills", "meadow", "grove", "jagged_peaks", "snowy_slopes", "frozen_peaks", "stony_peaks"}; + for (String emeraldBiome : emeraldBiomes) { + emeraldIndex.put(emeraldBiome, 27); + } + + ores.add(new Ore(Type.COAL, DimensionType.OVERWORLD_ID, 9, 6, ConstantIntProvider.create(30), false, 136, 320, Generator.DEFAULT, 17, coal, new Color(47, 44, 54))); + ores.add(new Ore(Type.COAL, DimensionType.OVERWORLD_ID, 10, 6, ConstantIntProvider.create(20), 1F, true, 97, 97, Generator.DEFAULT, 17, 0.5F, coal, new Color(47, 44, 54))); + ores.add(new Ore(Type.IRON, DimensionType.OVERWORLD_ID, 11, 6, ConstantIntProvider.create(90), true, 233, 153, Generator.DEFAULT, 9, iron, new Color(236, 173, 119))); + ores.add(new Ore(Type.IRON, DimensionType.OVERWORLD_ID, 12, 6, ConstantIntProvider.create(10), true, 17, 41, Generator.DEFAULT, 9, iron, new Color(236, 173, 119))); + ores.add(new Ore(Type.IRON, DimensionType.OVERWORLD_ID, 13, 6, ConstantIntProvider.create(10), false, -64, 73, Generator.DEFAULT, 4, iron, new Color(236, 173, 119))); + ores.add(new Ore(Type.GOLD_EXTRA, DimensionType.OVERWORLD_ID, extraGoldIndex, 6, ConstantIntProvider.create(50), false, 32, 257, Generator.DEFAULT, 9, gold, new Color(247, 229, 30))); + ores.add(new Ore(Type.GOLD, DimensionType.OVERWORLD_ID, 14, 6, ConstantIntProvider.create(4), 1F, true, -15, 49, Generator.DEFAULT, 9, 0.5F, gold, new Color(247, 229, 30))); + ores.add(new Ore(Type.GOLD, DimensionType.OVERWORLD_ID, 15, 6, UniformIntProvider.create(0, 1), 1F, false, -64, -47, Generator.DEFAULT, 9, 0.5F, gold, new Color(247, 229, 30))); + ores.add(new Ore(Type.REDSTONE, DimensionType.OVERWORLD_ID, 16, 6, ConstantIntProvider.create(4), false, -64, 16, Generator.DEFAULT, 8, redstone, new Color(245, 7, 23))); + ores.add(new Ore(Type.REDSTONE, DimensionType.OVERWORLD_ID, 17, 6, ConstantIntProvider.create(8), true, -63, 33, Generator.DEFAULT, 8, redstone, new Color(245, 7, 23))); + ores.add(new Ore(Type.DIAMOND, DimensionType.OVERWORLD_ID, 18, 6, ConstantIntProvider.create(7), 1F, true, -63, 81, Generator.DEFAULT, 4, 0.5F, diamond, new Color(33, 244, 255))); + ores.add(new Ore(Type.DIAMOND, DimensionType.OVERWORLD_ID, 19, 6, ConstantIntProvider.create(1), (1F / 9F), true, -63, 81, Generator.DEFAULT, 12, 0.7F, diamond, new Color(33, 244, 255))); + ores.add(new Ore(Type.DIAMOND, DimensionType.OVERWORLD_ID, 20, 6, ConstantIntProvider.create(4), 1F, true, -63, 81, Generator.DEFAULT, 8, 1F, diamond, new Color(33, 244, 255))); + ores.add(new Ore(Type.LAPIS, DimensionType.OVERWORLD_ID, 21, 6, ConstantIntProvider.create(2), true, 1, 33, Generator.DEFAULT, 7, lapis, new Color(8, 26, 189))); + ores.add(new Ore(Type.LAPIS, DimensionType.OVERWORLD_ID, 22, 6, ConstantIntProvider.create(4), 1F, false, -64, 65, Generator.DEFAULT, 7, 1F, lapis, new Color(8, 26, 189))); + ores.add(new Ore(Type.EMERALD, DimensionType.OVERWORLD_ID, emeraldIndex, 6, ConstantIntProvider.create(100), true, 233, 249, Generator.DEFAULT, 3, emerald, new Color(27, 209, 45))); + //This only generates near dripstone caves. I'll need propper biome detection to get this right + //ores.add(new Ore(Type.COPPER, "overworld", 23, 6, ConstantIntProvider.create(16), true, 49, 65, Generator.DEFAULT, 20, copper, new Color(239, 151, 0))); + ores.add(new Ore(Type.COPPER, DimensionType.OVERWORLD_ID, 24, 6, ConstantIntProvider.create(16), true, 49, 65, Generator.DEFAULT, 10, copper, new Color(239, 151, 0))); + ores.add(new Ore(Type.GOLD_NETHER, DimensionType.THE_NETHER_ID, Map.of("default", 19, "basalt_deltas", -1), 7, ConstantIntProvider.create(10), false, 10, 118, Generator.DEFAULT, 10, gold, new Color(247, 229, 30))); + ores.add(new Ore(Type.QUARTZ, DimensionType.THE_NETHER_ID, Map.of("default", 20, "basalt_deltas", -1), 7, ConstantIntProvider.create(16), false, 10, 118, Generator.DEFAULT, 14, quartz, new Color(205, 205, 205))); + ores.add(new Ore(Type.GOLD_NETHER, DimensionType.THE_NETHER_ID, Map.of("default", -1, "basalt_deltas", 13), 7, ConstantIntProvider.create(20), false, 10, 118, Generator.DEFAULT, 10, gold, new Color(247, 229, 30))); + ores.add(new Ore(Type.QUARTZ, DimensionType.THE_NETHER_ID, Map.of("default", -1, "basalt_deltas", 14), 7, ConstantIntProvider.create(32), false, 10, 118, Generator.DEFAULT, 14, quartz, new Color(205, 205, 205))); + ores.add(new Ore(Type.LDEBRIS, DimensionType.THE_NETHER_ID, 21, 7, ConstantIntProvider.create(1), true, 17, 9, Generator.NO_SURFACE, 3, debris, new Color(209, 27, 245))); + ores.add(new Ore(Type.SDEBRIS, DimensionType.THE_NETHER_ID, 22, 7, ConstantIntProvider.create(1), false, 8, 120, Generator.NO_SURFACE, 2, debris, new Color(209, 27, 245))); + return ores; + } + + private static List baseConfig() { + List ores = new ArrayList<>(); + HashMap emeraldIndexes = new HashMap<>(); + emeraldIndexes.put("default", -1); + String[] emeraldBiomes = new String[]{"mountains", "mountain_edge", "wooded_mountains", "gravelly_mountains", "modified_gravelly_mountains", "paper"}; + for (String emeraldBiome : emeraldBiomes) { + emeraldIndexes.put(emeraldBiome, 17); + } + HashMap LDebrisIndexes = new HashMap<>(); + LDebrisIndexes.put("default", 15); + LDebrisIndexes.put("crimson_forest", 12); + LDebrisIndexes.put("warped_forest", 13); + HashMap SDebrisIndexes = new HashMap<>(); + LDebrisIndexes.forEach((biome, index) -> SDebrisIndexes.put(biome, index + 1)); + HashMap extraGoldIndexes = new HashMap<>(); + extraGoldIndexes.put("default", -1); + String[] extraGoldBiomes = new String[]{"badlands", "badlands_plateau", "modified_badlands_plateau", "wooded_badlands_plateau", "modified_wooded_badlands_plateau", "eroded_badlands", "paper"}; + for (String extraGoldBiome : extraGoldBiomes) { + extraGoldIndexes.put(extraGoldBiome, 14); + } + ores.add(new Ore(Type.COAL, DimensionType.OVERWORLD_ID, 7, 6, ConstantIntProvider.create(20), false, 0, 128, Generator.DEFAULT, 20, coal, new Color(47, 44, 54))); + ores.add(new Ore(Type.IRON,DimensionType.OVERWORLD_ID, 8, 6, ConstantIntProvider.create(20), false, 0, 64, Generator.DEFAULT, 9, iron, new Color(236, 173, 119))); + ores.add(new Ore(Type.GOLD, DimensionType.OVERWORLD_ID, 9, 6, ConstantIntProvider.create(2), false, 0, 32, Generator.DEFAULT, 9, gold, new Color(247, 229, 30))); + ores.add(new Ore(Type.REDSTONE, DimensionType.OVERWORLD_ID, 10, 6, ConstantIntProvider.create(8), false, 0, 16, Generator.DEFAULT, 8, redstone, new Color(245, 7, 23))); + ores.add(new Ore(Type.DIAMOND, DimensionType.OVERWORLD_ID, 11, 6, ConstantIntProvider.create(1), false, 0, 16, Generator.DEFAULT, 8, diamond, new Color(33, 244, 255))); + ores.add(new Ore(Type.LAPIS, DimensionType.OVERWORLD_ID, 12, 6, ConstantIntProvider.create(1), true, 16, 16, Generator.DEFAULT, 7, lapis, new Color(8, 26, 189))); + ores.add(new Ore(Type.COPPER, DimensionType.OVERWORLD_ID, 13, 6, ConstantIntProvider.create(6), true, 49, 49, Generator.DEFAULT, 10, copper, new Color(239, 151, 0))); + ores.add(new Ore(Type.GOLD_EXTRA, DimensionType.OVERWORLD_ID, extraGoldIndexes, 6, ConstantIntProvider.create(20), false, 32, 80, Generator.DEFAULT, 9, gold, new Color(247, 229, 30))); + ores.add(new Ore(Type.EMERALD, DimensionType.OVERWORLD_ID, emeraldIndexes, 6, UniformIntProvider.create(6, 8), false, 4, 32, Generator.EMERALD, 1, emerald, new Color(27, 209, 45))); + ores.add(new Ore(Type.GOLD_NETHER, DimensionType.THE_NETHER_ID, Map.of("default", 13, "basalt_deltas", -1), 7, ConstantIntProvider.create(10), false, 10, 118, Generator.DEFAULT, 10, gold, new Color(247, 229, 30))); + ores.add(new Ore(Type.QUARTZ, DimensionType.THE_NETHER_ID, Map.of("default", 14, "basalt_deltas", -1), 7, ConstantIntProvider.create(16), false, 10, 118, Generator.DEFAULT, 14, quartz, new Color(205, 205, 205))); + ores.add(new Ore(Type.GOLD_NETHER, DimensionType.THE_NETHER_ID, Map.of("default", -1, "basalt_deltas", 13), 7, ConstantIntProvider.create(20), false, 10, 118, Generator.DEFAULT, 10, gold, new Color(247, 229, 30))); + ores.add(new Ore(Type.QUARTZ, DimensionType.THE_NETHER_ID, Map.of("default", -1, "basalt_deltas", 14), 7, ConstantIntProvider.create(32), false, 10, 118, Generator.DEFAULT, 14, quartz, new Color(205, 205, 205))); + ores.add(new Ore(Type.LDEBRIS, DimensionType.THE_NETHER_ID, LDebrisIndexes, 7, ConstantIntProvider.create(1), true, 17, 9, Generator.NO_SURFACE, 3, debris, new Color(209, 27, 245))); + ores.add(new Ore(Type.SDEBRIS, DimensionType.THE_NETHER_ID, SDebrisIndexes, 7, ConstantIntProvider.create(1), false, 8, 120, Generator.NO_SURFACE, 2, debris, new Color(209, 27, 245))); + return ores; + } + + private static List V1_17_1() { + return baseConfig(); + } + + private static List V1_17() { + List ores = baseConfig(); + for (Ore ore : ores) { + if (ore.type.equals(Type.DIAMOND)) { + ore.maxY = 17; + } + if (ore.type.equals(Type.EMERALD)) { + ore.count = UniformIntProvider.create(6, 24); + } + } + return ores; + } + + private static List V1_16() { + List ores = baseConfig(); + ores.removeIf(ore -> ore.type.equals(Type.COPPER)); + for (Ore ore : ores) { + if (ore.type == Type.EMERALD || ore.type == Type.GOLD_EXTRA) { + ore.index.keySet().forEach(key -> ore.index.put(key, ore.index.get(key) - 3)); + } else if (ore.dimension.equals("overworld")) { + ore.index.keySet().forEach(key -> ore.index.put(key, ore.index.get(key) - 2)); + } else if (ore.type == Type.LDEBRIS) { + ore.minY = 16; + ore.maxY = 8; + } + } + return ores; + } + + private static List V1_15() { + List ores = V1_16(); + ores.removeIf(ore -> ore.type == Type.SDEBRIS || ore.type == Type.LDEBRIS || ore.type == Type.GOLD_NETHER); + for (Ore ore : ores) { + ore.step -= 2; + } + return ores; + } + + protected static List getConfig(OreSim.Version version) { + return switch (version) { + case V1_18 -> V1_18(); + case V1_17_1 -> V1_17_1(); + case V1_17_0 -> V1_17(); + case V1_16 -> V1_16(); + case V1_15, V1_14 -> V1_15(); + }; + } + + protected enum Type { + DIAMOND, REDSTONE, GOLD, IRON, COAL, EMERALD, SDEBRIS, LDEBRIS, LAPIS, COPPER, QUARTZ, GOLD_NETHER, GOLD_EXTRA + } + + protected enum Generator { + DEFAULT, EMERALD, NO_SURFACE + } +} diff --git a/src/main/java/anticope/rejects/modules/OreSim.java b/src/main/java/anticope/rejects/modules/OreSim.java new file mode 100755 index 0000000..378d472 --- /dev/null +++ b/src/main/java/anticope/rejects/modules/OreSim.java @@ -0,0 +1,477 @@ +package anticope.rejects.modules; + +import anticope.rejects.MeteorRejectsAddon; +import anticope.rejects.events.ChunkPosDataEvent; +import anticope.rejects.events.SeedChangedEvent; +import anticope.rejects.utils.seeds.Seed; +import anticope.rejects.utils.seeds.Seeds; +import meteordevelopment.meteorclient.events.render.Render3DEvent; +import meteordevelopment.meteorclient.events.world.ChunkDataEvent; +import meteordevelopment.meteorclient.events.world.TickEvent; +import meteordevelopment.meteorclient.settings.EnumSetting; +import meteordevelopment.meteorclient.settings.IntSetting; +import meteordevelopment.meteorclient.settings.Setting; +import meteordevelopment.meteorclient.settings.SettingGroup; +import meteordevelopment.meteorclient.systems.modules.Module; +import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.meteorclient.systems.modules.movement.Scaffold; +import meteordevelopment.meteorclient.systems.modules.world.Nuker; +import meteordevelopment.meteorclient.utils.Utils; +import meteordevelopment.orbit.EventHandler; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.BufferRenderer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.Heightmap; +import net.minecraft.world.chunk.ChunkStatus; +import net.minecraft.world.chunk.WorldChunk; +import net.minecraft.world.gen.random.ChunkRandom; + +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Random; + +public class OreSim extends Module { + + private final HashMap>> chunkRenderers = new HashMap<>(); + Long worldSeed = null; + List oreConfig; + private ChunkPos prevOffset = new ChunkPos(0, 0); + + public enum Version { + V1_14, + V1_15, + V1_16, + V1_17_0, + V1_17_1, + V1_18 + } + + public enum AirCheck { + ON_LOAD, + RECHECK, + OFF + } + + private final SettingGroup sgGeneral = settings.getDefaultGroup(); + private final Setting horizontalRadius = sgGeneral.add(new IntSetting.Builder() + .name("chunk range") + .description("taxi cap distance of chunks being shown") + .defaultValue(5) + .min(1) + .sliderMax(10) + .build() + ); + + private final Setting airCheck = sgGeneral.add(new EnumSetting.Builder() + .name("Air check mode") + .description("checks if there is air at a calculated ore pos") + .defaultValue(AirCheck.RECHECK) + .build() + ); + + private final Setting version = sgGeneral.add(new EnumSetting.Builder() + .name("Air check mode") + .description("checks if there is air at a calculated ore pos") + .defaultValue(Version.V1_18) + .onChanged(v -> versionChanged()) + .build() + ); + + public OreSim() { + super(MeteorRejectsAddon.CATEGORY, "OreSim", "xray on crack"); + oreConfig = Ore.getConfig(version.get()); + Ore.oreSettings.forEach(sgGeneral::add); + } + + @EventHandler + private void onRender(Render3DEvent event) { + if (mc.player == null) { + return; + } + if (Seeds.get().getSeed() != null) { + int chunkX = mc.player.getChunkPos().x; + int chunkZ = mc.player.getChunkPos().z; + + int rangeVal = horizontalRadius.get(); + for (int range = 0; range <= rangeVal; range++) { + for (int x = -range + chunkX; x <= range + chunkX; x++) { + renderChunk(x, chunkZ + range - rangeVal, event); + } + for (int x = (-range) + 1 + chunkX; x < range + chunkX; x++) { + renderChunk(x, chunkZ - range + rangeVal + 1, event); + } + } + } + + } + + private void renderChunk(int x, int z, Render3DEvent event) { + long chunkKey = (long) x + ((long) z << 32); + + if (chunkRenderers.containsKey(chunkKey)) { + for (Ore ore : oreConfig) { + if (ore.enabled.get()) { + if (!chunkRenderers.get(chunkKey).containsKey(ore)) { + continue; + } + for (Vec3d pos : chunkRenderers.get(chunkKey).get(ore)) { + event.renderer.boxLines(pos.x,pos.y,pos.z,pos.x+1,pos.y+1,pos.z+1, ore.color,0); + } + } + } + } + } + + @EventHandler + public void onTick(TickEvent.Pre event) { + if (airCheck.get() == AirCheck.RECHECK) { + if (mc.player == null || mc.world == null) { + return; + } + long chunkX = mc.player.getChunkPos().x; + long chunkZ = mc.player.getChunkPos().z; + ClientWorld world = mc.world; + int renderdistance = MinecraftClient.getInstance().options.viewDistance; + + //maybe another config option? But its already crowded + int chunkCounter = 5; + + loop: + while (true) { + for (long offsetX = prevOffset.x; offsetX <= renderdistance; offsetX++) { + for (long offsetZ = prevOffset.z; offsetZ <= renderdistance; offsetZ++) { + prevOffset = new ChunkPos((int) offsetX, (int) offsetZ); + if (chunkCounter <= 0) { + break loop; + } + long chunkKey = (chunkX + offsetX) + ((chunkZ + offsetZ) << 32); + + if (chunkRenderers.containsKey(chunkKey)) { + chunkRenderers.get(chunkKey).values().forEach(oreSet -> oreSet.removeIf(ore -> !world.getBlockState(new BlockPos((int) ore.x, (int) ore.y, (int) ore.z)).isOpaque())); + } + chunkCounter--; + } + prevOffset = new ChunkPos((int) offsetX, -renderdistance); + } + prevOffset = new ChunkPos(-renderdistance, -renderdistance); + } + } + + } + + @Override + public void onActivate() { + if (Seeds.get().getSeed() == null) { + error("input a world seed into the seed field in the oresim config"); + this.toggle(); + } + reload(); + } + + @EventHandler + private void onSeedChanged(SeedChangedEvent event) { + reload(); + } + + private void versionChanged() { + this.oreConfig = Ore.getConfig(version.get()); + reload(); + } + + private void loadVisibleChunks() { + int renderdistance = MinecraftClient.getInstance().options.viewDistance; + + if (mc.player == null) { + return; + } + int playerChunkX = mc.player.getChunkPos().x; + int playerChunkZ = mc.player.getChunkPos().z; + + for (int i = playerChunkX - renderdistance; i < playerChunkX + renderdistance; i++) { + for (int j = playerChunkZ - renderdistance; j < playerChunkZ + renderdistance; j++) { + doMathOnChunk(i, j); + } + } + } + + public void reload() { + Seed seed = Seeds.get().getSeed(); + if (seed == null) return; + worldSeed = seed.seed; + chunkRenderers.clear(); + if (MinecraftClient.getInstance().world != null && worldSeed != null) { + loadVisibleChunks(); + } + } + + @EventHandler + public void onChunkData(ChunkPosDataEvent event) { + doMathOnChunk(event.chunkX, event.chunkZ); + } + + public void doMathOnChunk(int chunkX, int chunkZ) { + long chunkKey = (long) chunkX + ((long) chunkZ << 32); + + ClientWorld world = mc.world; + + if (chunkRenderers.containsKey(chunkKey) || world == null) { + return; + } + + if (world.getChunkManager().getChunk(chunkX, chunkZ, ChunkStatus.FULL, false) == null) { + return; + } + + chunkX = chunkX << 4; + chunkZ = chunkZ << 4; + + + ChunkRandom random = new ChunkRandom(ChunkRandom.RandomProvider.LEGACY.create(0)); + + if (version.get().ordinal() >= 5) { //1.18 and above + random = new ChunkRandom(ChunkRandom.RandomProvider.XOROSHIRO.create(0)); + } + + HashMap> h = new HashMap<>(); + + long populationSeed = random.setPopulationSeed(worldSeed, chunkX, chunkZ); + + Identifier id = world.getRegistryManager().get(Registry.BIOME_KEY).getId(world.getBiomeAccess().getBiomeForNoiseGen(new BlockPos(chunkX, 0, chunkZ))); + if (id == null) { + System.out.println("Something went wrong, you may have some mods that mess with world generation"); + this.toggle(); + return; + } + String biomeName = id.getPath(); + Identifier dimensionName = world.getDimension().getEffects(); + + for (Ore ore : oreConfig) { + + if (dimensionName != ore.dimension) { + continue; + } + + HashSet ores = new HashSet<>(); + + int index; + if (ore.index.containsKey(biomeName)) { + index = ore.index.get(biomeName); + } else { + index = ore.index.get("default"); + } + if (index < 0) { + continue; + } + + random.setDecoratorSeed(populationSeed, index, ore.step); + + int repeat = ore.count.get(random); + + for (int i = 0; i < repeat; i++) { + + if (ore.chance != 1F && random.nextFloat() >= ore.chance) { + continue; + } + + int x = random.nextInt(16) + chunkX; + int z; + int y; + if (version.get() == Version.V1_14) { + y = ore.depthAverage ? random.nextInt(ore.maxY) + random.nextInt(ore.maxY) - ore.maxY : random.nextInt(ore.maxY - ore.minY); + z = random.nextInt(16) + chunkZ; + } else { + z = random.nextInt(16) + chunkZ; + y = ore.depthAverage ? random.nextInt(ore.maxY) + random.nextInt(ore.maxY) - ore.maxY : random.nextInt(ore.maxY - ore.minY); + } + y += ore.minY; + + switch (ore.generator) { + case DEFAULT -> ores.addAll(generateNormal(world, random, new BlockPos(x, y, z), ore.size, ore.discardOnAir)); + case EMERALD -> { + if (airCheck.get() == AirCheck.OFF || world.getBlockState(new BlockPos(x, y, z)).isOpaque()) { + ores.add(new Vec3d(x, y, z)); + } + } + case NO_SURFACE -> ores.addAll(generateHidden(world, random, new BlockPos(x, y, z), ore.size)); + default -> System.out.println(ore.type + " has some unknown generator. Fix it!"); + } + } + if (!ores.isEmpty()) { + h.put(ore, ores); + } + } + chunkRenderers.put(chunkKey, h); + } + + // ==================================== + // Mojang code + // ==================================== + + private ArrayList generateNormal(ClientWorld world, Random random, BlockPos blockPos, int veinSize, float discardOnAir) { + float f = random.nextFloat() * 3.1415927F; + float g = (float) veinSize / 8.0F; + int i = MathHelper.ceil(((float) veinSize / 16.0F * 2.0F + 1.0F) / 2.0F); + double d = (double) blockPos.getX() + Math.sin(f) * (double) g; + double e = (double) blockPos.getX() - Math.sin(f) * (double) g; + double h = (double) blockPos.getZ() + Math.cos(f) * (double) g; + double j = (double) blockPos.getZ() - Math.cos(f) * (double) g; + double l = (blockPos.getY() + random.nextInt(3) - 2); + double m = (blockPos.getY() + random.nextInt(3) - 2); + int n = blockPos.getX() - MathHelper.ceil(g) - i; + int o = blockPos.getY() - 2 - i; + int p = blockPos.getZ() - MathHelper.ceil(g) - i; + int q = 2 * (MathHelper.ceil(g) + i); + int r = 2 * (2 + i); + + for (int s = n; s <= n + q; ++s) { + for (int t = p; t <= p + q; ++t) { + if (o <= world.getTopY(Heightmap.Type.MOTION_BLOCKING, s, t)) { + return this.generateVeinPart(world, random, veinSize, d, e, h, j, l, m, n, o, p, q, r, discardOnAir); + } + } + } + + return new ArrayList<>(); + } + + private ArrayList generateVeinPart(ClientWorld world, Random random, int veinSize, double startX, double endX, double startZ, double endZ, double startY, double endY, int x, int y, int z, int size, int i, float discardOnAir) { + + BitSet bitSet = new BitSet(size * i * size); + BlockPos.Mutable mutable = new BlockPos.Mutable(); + double[] ds = new double[veinSize * 4]; + + ArrayList poses = new ArrayList<>(); + + int n; + double p; + double q; + double r; + double s; + for (n = 0; n < veinSize; ++n) { + float f = (float) n / (float) veinSize; + p = MathHelper.lerp(f, startX, endX); + q = MathHelper.lerp(f, startY, endY); + r = MathHelper.lerp(f, startZ, endZ); + s = random.nextDouble() * (double) veinSize / 16.0D; + double m = ((double) (MathHelper.sin(3.1415927F * f) + 1.0F) * s + 1.0D) / 2.0D; + ds[n * 4] = p; + ds[n * 4 + 1] = q; + ds[n * 4 + 2] = r; + ds[n * 4 + 3] = m; + } + + for (n = 0; n < veinSize - 1; ++n) { + if (!(ds[n * 4 + 3] <= 0.0D)) { + for (int o = n + 1; o < veinSize; ++o) { + if (!(ds[o * 4 + 3] <= 0.0D)) { + p = ds[n * 4] - ds[o * 4]; + q = ds[n * 4 + 1] - ds[o * 4 + 1]; + r = ds[n * 4 + 2] - ds[o * 4 + 2]; + s = ds[n * 4 + 3] - ds[o * 4 + 3]; + if (s * s > p * p + q * q + r * r) { + if (s > 0.0D) { + ds[o * 4 + 3] = -1.0D; + } else { + ds[n * 4 + 3] = -1.0D; + } + } + } + } + } + } + + for (n = 0; n < veinSize; ++n) { + double u = ds[n * 4 + 3]; + if (!(u < 0.0D)) { + double v = ds[n * 4]; + double w = ds[n * 4 + 1]; + double aa = ds[n * 4 + 2]; + int ab = Math.max(MathHelper.floor(v - u), x); + int ac = Math.max(MathHelper.floor(w - u), y); + int ad = Math.max(MathHelper.floor(aa - u), z); + int ae = Math.max(MathHelper.floor(v + u), ab); + int af = Math.max(MathHelper.floor(w + u), ac); + int ag = Math.max(MathHelper.floor(aa + u), ad); + + for (int ah = ab; ah <= ae; ++ah) { + double ai = ((double) ah + 0.5D - v) / u; + if (ai * ai < 1.0D) { + for (int aj = ac; aj <= af; ++aj) { + double ak = ((double) aj + 0.5D - w) / u; + if (ai * ai + ak * ak < 1.0D) { + for (int al = ad; al <= ag; ++al) { + double am = ((double) al + 0.5D - aa) / u; + if (ai * ai + ak * ak + am * am < 1.0D) { + int an = ah - x + (aj - y) * size + (al - z) * size * i; + if (!bitSet.get(an)) { + bitSet.set(an); + mutable.set(ah, aj, al); + if (aj >= -64 && aj < 320 && (airCheck.get() == AirCheck.OFF || world.getBlockState(mutable).isOpaque())) { + if (shouldPlace(world, mutable, discardOnAir, random)) { + poses.add(new Vec3d(ah, aj, al)); + } + } + } + } + } + } + } + } + } + } + } + + return poses; + } + + private boolean shouldPlace(ClientWorld world, BlockPos orePos, float discardOnAir, Random random) { + if (discardOnAir == 0F || (discardOnAir != 1F && random.nextFloat() >= discardOnAir)) { + return true; + } + + for (Direction direction : Direction.values()) { + if (!world.getBlockState(orePos.add(direction.getVector())).isOpaque() && discardOnAir != 1F) { + return false; + } + } + return true; + } + + private ArrayList generateHidden(ClientWorld world, Random random, BlockPos blockPos, int size) { + + ArrayList poses = new ArrayList<>(); + + int i = random.nextInt(size + 1); + + for (int j = 0; j < i; ++j) { + size = Math.min(j, 7); + int x = this.randomCoord(random, size) + blockPos.getX(); + int y = this.randomCoord(random, size) + blockPos.getY(); + int z = this.randomCoord(random, size) + blockPos.getZ(); + if (airCheck.get() == AirCheck.OFF || world.getBlockState(new BlockPos(x, y, z)).isOpaque()) { + if (shouldPlace(world, new BlockPos(x, y, z), 1F, random)) { + poses.add(new Vec3d(x, y, z)); + } + } + } + + return poses; + } + + private int randomCoord(Random random, int size) { + return Math.round((random.nextFloat() - random.nextFloat()) * (float) size); + } +} diff --git a/src/main/java/anticope/rejects/utils/seeds/Seeds.java b/src/main/java/anticope/rejects/utils/seeds/Seeds.java index 843a3c8..12fd7a2 100644 --- a/src/main/java/anticope/rejects/utils/seeds/Seeds.java +++ b/src/main/java/anticope/rejects/utils/seeds/Seeds.java @@ -2,6 +2,7 @@ package anticope.rejects.utils.seeds; import java.util.HashMap; +import anticope.rejects.events.SeedChangedEvent; import net.minecraft.client.network.ServerInfo; import net.minecraft.nbt.NbtCompound; import net.minecraft.text.BaseText; @@ -48,7 +49,9 @@ public class Seeds extends System { public void setSeed(String seed, MCVersion version) { if (mc.isIntegratedServerRunning()) return; - seeds.put(Utils.getWorldName(), new Seed(toSeed(seed), version)); + long numSeed = toSeed(seed); + seeds.put(Utils.getWorldName(), new Seed(numSeed, version)); + MeteorClient.EVENT_BUS.post(SeedChangedEvent.get(numSeed)); } public void setSeed(String seed) { diff --git a/src/main/resources/meteor-rejects.mixins.json b/src/main/resources/meteor-rejects.mixins.json index 8e94085..dc8b3c1 100644 --- a/src/main/resources/meteor-rejects.mixins.json +++ b/src/main/resources/meteor-rejects.mixins.json @@ -3,6 +3,7 @@ "package": "anticope.rejects.mixin", "compatibilityLevel": "JAVA_16", "client": [ + "ClientPlayNetworkHandlerMixin", "CommandSuggestorMixin", "CustomPayloadS2CPacketMixin", "Deadmau5FeatureRendererMixin",