-
-
Save BrainStone/8f4a453b05189645a4d077d0ace72fcc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
out/ | |
.idea/ | |
*.iml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.ArrayList; | |
import java.util.LinkedHashMap; | |
import java.util.Map; | |
public class Main { | |
public static void printTableForPublic( | |
MinecraftOreOffsetFinder.Disk disk, MinecraftOreOffsetFinder.Ore ore, int maxLines) { | |
int total = 0; | |
for (int i = 0; i < 16; i++) { | |
if (MinecraftOreOffsetFinder.residueOrSeedReliable(disk, ore, i)) { | |
total++; | |
} | |
} | |
System.out.println( | |
disk + " " + ore + " will work reliably on " + (total / 16.0 * 100) + "% of seeds."); | |
LinkedHashMap<ArrayList<Integer>, Double> offsets = | |
MinecraftOreOffsetFinder.getOffsets(disk, ore); | |
int i = 0; | |
for (Map.Entry<ArrayList<Integer>, Double> entry : offsets.entrySet()) { | |
if (++i > maxLines) { | |
break; | |
} | |
System.out.printf( | |
"Z offset %d occurs with probability %.2f%%\n", | |
entry.getKey().get(0), entry.getValue() * 100); | |
} | |
System.out.println(); | |
} | |
private static void printStatsForAllSeeds() { | |
final int MAX_LINES = 5; | |
for (MinecraftOreOffsetFinder.Disk disk : MinecraftOreOffsetFinder.Disk.values()) { | |
for (MinecraftOreOffsetFinder.Ore ore : MinecraftOreOffsetFinder.Ore.values()) { | |
printTableForPublic(disk, ore, MAX_LINES); | |
} | |
} | |
} | |
private static void printStatsForSeed(long seed) { | |
for (MinecraftOreOffsetFinder.Disk disk : MinecraftOreOffsetFinder.Disk.values()) { | |
System.out.println(disk + ":"); | |
for (MinecraftOreOffsetFinder.Ore ore : MinecraftOreOffsetFinder.Ore.values()) { | |
boolean reliable = MinecraftOreOffsetFinder.residueOrSeedReliable(disk, ore, seed); | |
int offset = MinecraftOreOffsetFinder.getOffsetsForSeed(disk, ore, seed).get(0); | |
System.out.printf("%s offset: %d%s reliable\n", ore, offset, reliable ? "" : " NOT"); | |
} | |
System.out.println(); | |
} | |
} | |
public static void main(String[] args) { | |
if (args.length == 0) { | |
printStatsForAllSeeds(); | |
} else { | |
printStatsForSeed(Long.parseLong(args[0])); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.LinkedHashMap; | |
import java.util.Map; | |
import java.util.Random; | |
import java.util.stream.Collectors; | |
public class MinecraftOreOffsetFinder { | |
// Constant used in java.util.Random to multiply the current seed with and also to XOR the initial | |
// seed | |
private static final long lmult = 0x5deece66dL; | |
private static final long mask = (1L << 48) - 1; | |
private static final int seedsToSearch = 1000000; | |
public static enum Ore { | |
COAL(60005), | |
IRON(60006), | |
GOLD(60007), | |
REDSTONE(60008), | |
DIAMOND(60009), | |
LAPIS(60010); | |
public final int salt; | |
private Ore(int salt) { | |
this.salt = salt; | |
} | |
} | |
public enum Disk { | |
SWAMP_CLAY(60011), | |
RIVER_CLAY(60012), | |
GRAVEL(60013); | |
public final int salt; | |
private Disk(int salt) { | |
this.salt = salt; | |
} | |
} | |
private static int seedToOffset(long seed) { | |
final int precision = 16; | |
final long blockToSeed = (1L << 48) / precision; | |
long s1 = (seed * lmult) & mask; | |
long s2 = (s1 * lmult) & mask; | |
return (int) (s2 / blockToSeed); | |
} | |
private static ArrayList<Long> getOffsetsForSeedRaw(long[] salts, Ore ore, long seed) { | |
long targetSalt = ore.salt; | |
ArrayList<Long> offsets = new ArrayList<>(salts.length); | |
for (long salt : salts) { | |
offsets.add((((seed + targetSalt) ^ lmult) - ((seed + salt) ^ lmult)) & mask); | |
} | |
return offsets; | |
} | |
private static ArrayList<Integer> getOffsetsForSeed(long[] salts, Ore ore, long seed) { | |
return getOffsetsForSeedRaw(salts, ore, seed).stream() | |
.map(MinecraftOreOffsetFinder::seedToOffset) | |
.collect(Collectors.toCollection(ArrayList::new)); | |
} | |
public static ArrayList<Integer> getOffsetsForSeed(Disk disk, Ore ore, long seed) { | |
return getOffsetsForSeed(new long[] {disk.salt}, ore, seed); | |
} | |
private static HashMap<ArrayList<Long>, Integer> getOffsetsRaw(Disk disk, Ore ore) { | |
HashMap<ArrayList<Long>, Integer> offsets = new HashMap<>(); | |
Random r = new Random(); | |
long targetSalt = ore.salt; | |
long[] measuredSalts = {disk.salt}; // intent is eventually to handle multiple decorators | |
long seed; | |
for (int i = 0; i < seedsToSearch; i++) { | |
seed = r.nextLong() & mask; | |
ArrayList<Long> key = getOffsetsForSeedRaw(measuredSalts, ore, seed); | |
if (offsets.containsKey(key)) { | |
int current = offsets.get(key); | |
offsets.replace(key, current + 1); | |
} else { | |
offsets.put(key, 1); | |
} | |
} | |
return offsets; | |
} | |
public static LinkedHashMap<ArrayList<Integer>, Double> getOffsets(Disk disk, Ore ore) { | |
HashMap<ArrayList<Long>, Integer> rawOffsets = getOffsetsRaw(disk, ore); | |
return rawOffsets.entrySet().stream() | |
.sorted(Map.Entry.<ArrayList<Long>, Integer>comparingByValue().reversed()) | |
.collect( | |
Collectors.toMap( | |
entry -> | |
entry.getKey().stream() | |
.map(MinecraftOreOffsetFinder::seedToOffset) | |
.collect(Collectors.toCollection(ArrayList::new)), | |
entry -> entry.getValue() / ((double) seedsToSearch), | |
(u, v) -> u, | |
LinkedHashMap::new)); | |
} | |
public static boolean residueOrSeedReliable(Disk disk, Ore ore, long residueOrSeed) { | |
return ((disk.salt + residueOrSeed) & 0x10) == ((ore.salt + residueOrSeed) & 0x10); | |
} | |
} |
@joogle12 not sure why you didn't just use my gist, to update the salts there. Then you'd still have the dual program.
What needs to be done to update for 1.17?
Hey. Check my gist profile for the 1.17 version. Works on most seeds.
…Sent from my iPhone
On Nov 12, 2021, at 1:47 AM, George N ***@***.***> wrote:
***@***.*** commented on this gist.
What needs to be done to update for 1.17?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or unsubscribe.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
hey. thanks for the help man. I made a 1.17 version by taking a few tips and updating the salts.