Advertisement
Guest User

Untitled

a guest
Jan 20th, 2020
487
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.16 KB | None | 0 0
  1. import java.util.ArrayList;
  2. import java.util.Random;
  3.  
  4.  
  5. public class ReverseDecoratorHashRefactored {
  6.  
  7. public static int countTrailingZeroes(long v) {
  8. int c; // output: c will count v's trailing zero bits,
  9. // so if v is 1101000 (base 2), then c will be 3
  10. v = (v ^ (v - 1)) >> 1; // Set v's trailing 0s to 1s and zero rest
  11. for (c = 0; v !=0; c++)
  12. {
  13. v >>>= 1;
  14. }
  15. return c;
  16. }
  17.  
  18. public static long modInverse(long x, int mod) { //Fast method for modular inverse mod powers of 2
  19. long inv = 0;
  20. long b = 1;
  21. for (int i = 0; i < mod; i++) {
  22. if ((b & 1)==1) {
  23. inv |= 1L << i;
  24. b = (b - x) >> 1;
  25. } else {
  26. b >>= 1;
  27. }
  28. }
  29. return inv;
  30. }
  31.  
  32. public static long getChunkseed(long seed, int x, int z) {
  33. Random r = new Random(seed);
  34. long a = r.nextLong()|1;
  35. long b = r.nextLong()|1;
  36. return ((x*a + z*b)^seed) & ((1L << 48) - 1);
  37. }
  38.  
  39. private static final long mask16 = 0xffffL;
  40. private static final long mask32 = 0xffff_ffffL;
  41.  
  42. private static final long m1 = 25214903917L; //the next 8 lines are constants for the lcg created by calling java lcg multiple times.
  43. // private static final long addend1 = 11;
  44. private static final long m2 = 205749139540585L;
  45. private static final long addend2 = 277363943098L;
  46. // private static final long m3 = 233752471717045L;
  47. // private static final long addend3 = 11718085204285L;
  48. private static final long m4 = 55986898099985L;
  49. private static final long addend4 = 49720483695876L;
  50. private static ArrayList<Long> worldseeds;
  51.  
  52. public static ArrayList<Long> getSeedFromChunkseed(long chunkseed, int x, int z) {
  53.  
  54. worldseeds = new ArrayList<>();
  55.  
  56. if (x == 0 && z == 0) {
  57. worldseeds.add(chunkseed);
  58. return worldseeds;
  59. }
  60.  
  61. long c; //a is upper 16 bits, b middle 16 bits, c lower 16 bits of worldseed.
  62. long e = chunkseed & ((1L << 32) - 1); //The algorithm proceeds by solving for worldseed in 16 bit groups
  63. long f = chunkseed & (((1L << 16) - 1)); //as such, we need the 16 bit groups of chunkseed for later eqns.
  64.  
  65. boolean xEven = ((x&1) == 0);
  66. boolean zEven = ((z&1) == 0);
  67.  
  68. long firstMultiplier = (m2*x + m4*z) & mask16;
  69. int multTrailingZeroes = countTrailingZeroes(firstMultiplier); //TODO currently code blows up if this is 16, but you can use it to get bits of seed anyway if it is non zero
  70. long firstMultInv = modInverse(firstMultiplier >> multTrailingZeroes,16);
  71.  
  72.  
  73. //TODO We can recover more initial bits when x + z is divisible by a power of 2
  74. if (xEven ^ zEven) { //bottom bit of x*a + z*b is odd so we xor by 1 to get bottom bit of worldseed.
  75. c = (chunkseed & 1)^1;
  76. } else { //bottom bit of x*a + z*b is even so we xor by 0 to get bottom bit of worldseed.
  77. c = (chunkseed & 1);
  78. }
  79.  
  80. for (; c < (1L << 16); c+=2) { //iterate through all possible lower 16 bits of worldseed.
  81. long target = (c ^ f) & mask16; //now that we've guessed 16 bits of worldseed we can undo the mask
  82.  
  83. //We need to handle the four different cases of the effect the two |1s have on the seed
  84. long magic = x * ((m2 * ((c ^ m1) & mask16) + addend2) >>> 16) + z * ((m4 * ((c ^ m1) & mask16) + addend4) >>> 16);
  85.  
  86. addWorldSeed(target - (magic & mask16), multTrailingZeroes, firstMultInv, c, e, x, z, chunkseed); //case both nextLongs were odd
  87.  
  88. addWorldSeed(target - ((magic + x) & mask16), multTrailingZeroes, firstMultInv, c, e, x, z, chunkseed); //case where x nextLong even
  89.  
  90. addWorldSeed(target - ((magic + z) & mask16), multTrailingZeroes, firstMultInv, c, e, x, z, chunkseed); //case where z nextLong even
  91.  
  92. addWorldSeed(target - ((magic + x + z) & mask16), multTrailingZeroes, firstMultInv, c, e, x, z, chunkseed); //case where both nextLongs even
  93. }
  94.  
  95. return worldseeds;
  96. }
  97.  
  98. public static long makeSecondAddend(int x, long k, int z) {
  99. return ((((long)x)*(((int)(((m2*((k^m1)& mask32) + addend2) & ((1L<<48)-1)) >>> 16))|1) +
  100. ((long)z)*(((int)(((m4*((k^m1)& mask32) + addend4) & ((1L<<48)-1)) >>> 16))|1)) >>> 16) & mask16;
  101. }
  102.  
  103. public static void addWorldSeed(long firstAddend, int multTrailingZeroes, long firstMultInv, long c, long e, int x, int z, long chunkseed){
  104. if (countTrailingZeroes(firstAddend) >= multTrailingZeroes) { //Does there exist a set of 16 bits which work for bits 17-32
  105. long b = ((((firstMultInv * firstAddend)>>> multTrailingZeroes)^(m1 >> 16)) & ((1L << (16-multTrailingZeroes))-1));
  106. //System.out.println(Long.toHexString(b));
  107. for(; b < (1L << 16); b += (1L << (16 - multTrailingZeroes))) { //if the previous multiplier had a power of 2 divisor, we get multiple solutions for b
  108. long k = (b << 16) + c;
  109. long target2 = (k ^ e) >> 16; //now that we know b, we can undo more of the mask
  110. long secondAddend = makeSecondAddend(x, k, z);
  111. if (countTrailingZeroes(target2 - secondAddend) >= multTrailingZeroes) { //Does there exist a set of 16 bits which work for bits 33-48
  112. long a = ((((firstMultInv * (target2 - secondAddend)) >>> multTrailingZeroes)^(m1 >> 32)) & ((1L << (16-multTrailingZeroes))-1));
  113. for(; a < (1L << 16); a += (1L << (16 - multTrailingZeroes))) { //if the previous multiplier had a power of 2 divisor, we get multiple solutions for a
  114. if (getChunkseed((a << 32) + k, x, z) == chunkseed) { //lazy check if the test has succeeded
  115. worldseeds.add((a << 32) + k);
  116. }
  117. }
  118. }
  119. }
  120. }
  121. }
  122.  
  123. public static void main(String[] args) {
  124. long seed;
  125. int x , z;
  126. ArrayList<Long> seeds;
  127. /*long seed = 40820992642153L;
  128. int x = 2;
  129. int z = 4;
  130. ArrayList<Long> seeds = getSeedFromChunkseed(getChunkseed(seed, x, z), x, z);
  131. System.out.println("start");
  132. for (long a : seeds) {
  133. System.out.println(a);
  134. }
  135. System.out.println("done");*/
  136. Random r = new Random();
  137. int failcount = 0;
  138. System.out.println("start");
  139. long start = System.currentTimeMillis();
  140. for(int i = 0; i < 100000; i++){
  141. seed = r.nextLong() & ((1L << 48)-1);
  142. x = r.nextInt(16) - 8;
  143. z = r.nextInt(16) - 8;
  144. seeds = getSeedFromChunkseed(getChunkseed(seed,x,z),x,z);
  145. if (!seeds.contains(seed)) {
  146. System.out.println(seed);
  147. System.out.println(x);
  148. System.out.println(z);
  149. failcount++;
  150. System.out.println();
  151. }
  152. }
  153. System.out.println("End: "+((System.currentTimeMillis()-start)/1000.0));
  154. System.out.println(failcount+" failures.");
  155. }
  156. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement