An unofficial collection of APIs used in FreeJam games and mods
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

75 lines
2.6KB

  1. use fasthash::murmur3::hash32_with_seed;
  2. use std::sync::mpsc::{channel, Sender};
  3. use std::thread;
  4. const HASH_SEED: u32 = 4919;
  5. const ASCII_LETTERS: &[u8] = &[65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90, // A..Z
  6. 97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122]; // a..z
  7. const ASCII_NUMBERS: &[u8] = &[48, 49, 50, 51, 52, 53, 54, 55, 56, 57]; // 0..9
  8. const HASHNAME_ENDING: &[u8] = &[69, 110, 116, 105, 116, 121, // Entity
  9. 68, 101, 115, 99, 114, 105, 112, 116, 111, 114, // Descriptor
  10. 86, 42]; // EntityDescriptorV0
  11. const MAX_LENGTH: usize = 10;
  12. pub fn hashname(name: &str) -> u32 {
  13. hash32_with_seed(name, HASH_SEED)
  14. }
  15. pub fn brute_force(hash: u32) -> String {
  16. let (tx, rx) = channel::<String>();
  17. let mut start = Vec::<u8>::new();
  18. thread::spawn(move || brute_force_letter(hash, &mut start, &tx, 1));
  19. //println!("All brute force possibilities explored");
  20. if let Ok(res) = rx.recv_timeout(std::time::Duration::from_secs(30)) {
  21. return res;
  22. } else {
  23. return "".to_string();
  24. }
  25. }
  26. fn brute_force_letter(hash: u32, start: &mut Vec<u8>, tx: &Sender<String>, threadity: usize) {
  27. if start.len() > 0 {
  28. brute_force_endings(hash, start, tx);
  29. }
  30. if start.len() >= MAX_LENGTH { // do not continue extending forever
  31. //handles.pop().unwrap().join().unwrap();
  32. return;
  33. }
  34. let mut handles = Vec::<thread::JoinHandle::<_>>::new();
  35. start.push(65); // add letter
  36. let last_elem = start.len()-1;
  37. for letter in ASCII_LETTERS {
  38. start[last_elem] = *letter;
  39. if threadity > 0 {
  40. //thread::sleep(std::time::Duration::from_millis(50));
  41. let mut new_start = start.clone();
  42. let new_tx = tx.clone();
  43. handles.push(thread::spawn(move || brute_force_letter(hash, &mut new_start, &new_tx, threadity-1)));
  44. } else {
  45. brute_force_letter(hash, start, tx, threadity);
  46. }
  47. }
  48. for handle in handles {
  49. handle.join().unwrap()
  50. }
  51. start.truncate(last_elem);
  52. }
  53. fn brute_force_endings(hash: u32, start: &mut Vec<u8>, tx: &Sender<String>) {
  54. start.extend(HASHNAME_ENDING); // add ending
  55. let last_elem = start.len()-1;
  56. for num in ASCII_NUMBERS {
  57. start[last_elem] = *num;
  58. if hash32_with_seed(&start, HASH_SEED) == hash {
  59. let result = String::from_utf8(start.clone()).unwrap();
  60. println!("Found match `{}`", result);
  61. tx.send(result).unwrap();
  62. }
  63. }
  64. start.truncate(start.len()-HASHNAME_ENDING.len()); // remove ending
  65. }