17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
|
# File 'lib/orefinder_estimate/estimate.rb', line 17
def estimate(input)
return error('invalid_body', 'Input must be a hash.') unless input.is_a?(Hash)
ore_in = input['ore'].is_a?(String) ? input['ore'].strip.downcase : ''
compute_key, display_label = Data.resolve_ore_keys(ore_in)
return error('invalid_ore', 'Unknown ore for estimator.') if ore_in.empty? || !Data.known_ore?(ore_in)
px = to_num(input['x'])
pz = to_num(input['z'])
py = input['y'].nil? ? 64.0 : to_num(input['y'])
if px.nil? || pz.nil? || py.nil? || !px.finite? || !pz.finite? || !py.finite?
return error('invalid_position', 'x, y and z must be finite numbers.')
end
version_field = input['version'] || input['platform'] || ''
parsed = Version.parse_version(version_field.to_s)
return error('invalid_version', 'Pass a version like "java_1_21" or "1.20.1".') if parsed.nil?
cfg = Data.era_config(parsed['era'], compute_key)
if cfg.nil?
msg = compute_key == 'copper' && parsed['era'] == 'legacy' ? 'Copper is modern-only (1.18+).' : 'This ore/version combination has no dataset row.'
return error('ore_not_in_era', msg)
end
need_mc = cfg['specialRules'] ? cfg['specialRules']['minMcMinor'] : nil
if need_mc.is_a?(Integer) && parsed['mcMinor'] < need_mc
return error('version_too_old_for_ore',
"This target needs Minecraft 1.#{need_mc}+ (you selected 1.#{parsed['mcMinor']}).",
'minMcMinor' => need_mc, 'selectedMcMinor' => parsed['mcMinor'])
end
biome = input['biome']
raw_biome = biome.is_a?(String) && !biome.strip.empty? ? biome.strip.downcase.gsub(/\s+/, '_') : 'plains'
biome_effective = Probability.normalize_biome(cfg, raw_biome)
radius_val = input['searchRadius'].nil? ? 220.0 : to_num(input['searchRadius'])
search_radius = [[radius_val, 32].max, 512].min.to_i
seed = input['seed'].nil? ? 'numeric' : input['seed']
clusters = Cluster.generate_clusters(
seed: seed, ore: compute_key, era: parsed['era'], cfg: cfg,
px: px, pz: pz, biome: raw_biome, search_radius: search_radius
)
peak_y = Probability.optimal_y_for_mining(cfg)
effect = Probability.biome_multiplier(cfg, biome_effective)
{
'success' => true,
'ore' => display_label,
'computeKey' => compute_key,
'bestCluster' => clusters['bestCluster'],
'secondaryClusters' => clusters['secondaryClusters'],
'metadata' => {
'ore' => display_label,
'computeKey' => compute_key,
'edition' => parsed['edition'],
'era' => parsed['era'],
'mcMinor' => parsed['mcMinor'],
'versionLabel' => parsed['raw'],
'optimalY' => cfg['optimalY'],
'practicalY' => cfg['practicalY'],
'actualPeakY' => cfg['actualPeakY'],
'yRange' => [cfg['minY'], cfg['maxY']],
'biomeRequested' => raw_biome,
'biomeEffective' => biome_effective,
'dimension' => cfg['dimension'] || 'overworld',
'biomeEffect' => Rng.round_half_up(effect * 1000) / 1000.0,
'miningPeakY' => peak_y,
'generation' => 'distribution_cluster_estimate',
'approximate' => true
}
}
end
|