217 lines
5.9 KiB
Ruby
Executable File
217 lines
5.9 KiB
Ruby
Executable File
#!/usr/bin/env ruby
|
|
|
|
require "json"
|
|
require "set"
|
|
|
|
# Run with gen-stats.rb <server_directory>
|
|
SERVER_DIR = ARGV[0] || "."
|
|
|
|
ADVENTURE_BIOMES = [
|
|
"Beach",
|
|
"Birch Forest",
|
|
"Birch Forest Hills",
|
|
"Cold Beach",
|
|
"Cold Taiga",
|
|
"Cold Taiga Hills",
|
|
"Deep Ocean",
|
|
"Desert",
|
|
"DesertHills",
|
|
"Extreme Hills",
|
|
"Extreme Hills+",
|
|
"Forest",
|
|
"ForestHills",
|
|
"FrozenRiver",
|
|
"Ice Mountains",
|
|
"Ice Plains",
|
|
"Jungle",
|
|
"JungleEdge",
|
|
"JungleHills",
|
|
"Mega Taiga",
|
|
"Mega Taiga Hills",
|
|
"Mesa",
|
|
"Mesa Plateau",
|
|
"Mesa Plateau F",
|
|
"MushroomIsland",
|
|
"MushroomIslandShore",
|
|
"Ocean",
|
|
"Plains",
|
|
"River",
|
|
"Roofed Forest",
|
|
"Savanna",
|
|
"Savanna Plateau",
|
|
"Stone Beach",
|
|
"Swampland",
|
|
"Taiga",
|
|
"TaigaHills",
|
|
]
|
|
|
|
class GenStats
|
|
def initialize
|
|
@all_explored_biomes = []
|
|
end
|
|
|
|
def run
|
|
user_cache = JSON.load(File.read("#{SERVER_DIR}/usercache.json"))
|
|
@users_by_uuid = user_cache.reduce({}) do |result, user|
|
|
result[user["uuid"]] = user
|
|
result
|
|
end
|
|
|
|
@all_stats = {
|
|
"Play Time" => {},
|
|
"Achievements" => {},
|
|
"Unexplored Biomes" => {},
|
|
"Deaths" => {},
|
|
"Damage Dealt" => {},
|
|
"Damage Taken" => {},
|
|
"Mob Kills" => {},
|
|
"Killed" => {},
|
|
"Killed By" => {},
|
|
"Items Broken" => {},
|
|
"Enchant Item Count" => {},
|
|
"Animals Bred" => {},
|
|
"Foot Travel Distance" => {},
|
|
"Horse Travel Distance" => {},
|
|
"Boat Travel Distance" => {},
|
|
"Crouch Distance" => {},
|
|
"Climb Distance" => {},
|
|
"Fall Distance" => {},
|
|
"Walk Under Water Distance" => {},
|
|
"Walk On Water Distance" => {},
|
|
}
|
|
Dir["#{SERVER_DIR}/world/stats/*.json"].each do |stats_fname|
|
|
load_stats(stats_fname)
|
|
end
|
|
|
|
print_stats
|
|
end
|
|
|
|
private
|
|
|
|
def load_stats(stats_fname)
|
|
File.basename(stats_fname) =~ /^(.*)\.json/
|
|
user_name =
|
|
if @users_by_uuid[$1]
|
|
@users_by_uuid[$1]["name"]
|
|
else
|
|
$1
|
|
end
|
|
stats_file = JSON.load(File.read(stats_fname))
|
|
stats = stats_file["stats"] || {}
|
|
stats["minecraft:custom"] ||= {}
|
|
|
|
@all_stats["Play Time"][user_name] =
|
|
begin
|
|
# stat is actually in ticks apparently
|
|
minutes = (stats["minecraft:custom"]["minecraft:play_one_minute"] || 0) / 20 / 60
|
|
hours = (minutes / 60).floor
|
|
minutes -= (hours * 60)
|
|
days = (hours / 24).floor
|
|
hours -= (days * 24)
|
|
"#{days}d #{hours}h #{minutes}m"
|
|
end
|
|
|
|
# @all_stats["Achievements"][user_name] =
|
|
# stats.find_all do |stat_name, stat_value|
|
|
# stat_name.start_with?("achievement.") and (stat_value.is_a?(Integer) or (stat_value.is_a?(Hash) and stat_value["value"] and stat_value["value"] > 0))
|
|
# end.size
|
|
|
|
# @all_stats["Unexplored Biomes"][user_name] =
|
|
# if stats["achievement.exploreAllBiomes"]
|
|
# explored_biomes = stats["achievement.exploreAllBiomes"]["progress"]
|
|
# unexplored_biomes = ADVENTURE_BIOMES - explored_biomes
|
|
# @all_explored_biomes += explored_biomes
|
|
# unexplored_biomes.sort.join(", ")
|
|
# end
|
|
|
|
@all_stats["Deaths"][user_name] = stats["minecraft:custom"]["minecraft:deaths"] || 0
|
|
|
|
@all_stats["Damage Dealt"][user_name] = stats["minecraft:custom"]["minecraft:damage_dealt"] || 0
|
|
|
|
@all_stats["Damage Taken"][user_name] = stats["minecraft:custom"]["minecraft:damage_taken"] || 0
|
|
|
|
@all_stats["Mob Kills"][user_name] = stats["minecraft:custom"]["minecraft:mob_kills"] || 0
|
|
|
|
@all_stats["Killed"][user_name] =
|
|
(stats["minecraft:killed"] || {}).reduce({}) do |result, (stat_name, stat_value)|
|
|
if stat_name =~ /^minecraft:(\w+)$/
|
|
result[$1] = stat_value
|
|
end
|
|
result
|
|
end
|
|
|
|
@all_stats["Killed By"][user_name] =
|
|
(stats["minecraft:killed_by"] || {}).reduce({}) do |result, (stat_name, stat_value)|
|
|
if stat_name =~ /^minecraft:(\w+)$/
|
|
result[$1] = stat_value
|
|
end
|
|
result
|
|
end
|
|
|
|
@all_stats["Items Broken"][user_name] =
|
|
(stats["minecraft:broken"] || {}).reduce({}) do |result, (stat_name, stat_value)|
|
|
if stat_name =~ /^minecraft:(\w+)$/
|
|
result[$1] = stat_value
|
|
end
|
|
result
|
|
end
|
|
|
|
@all_stats["Enchant Item Count"][user_name] = stats["minecraft:custom"]["minecraft:enchant_item"]
|
|
|
|
@all_stats["Animals Bred"][user_name] = stats["minecraft:custom"]["minecraft:animals_bred"]
|
|
|
|
{
|
|
"Foot Travel Distance" => ["sprint_one_cm", "walk_one_cm"],
|
|
"Horse Travel Distance" => ["horse_one_cm"],
|
|
"Boat Travel Distance" => ["boat_one_cm"],
|
|
"Crouch Distance" => ["crouch_one_cm"],
|
|
"Climb Distance" => ["climb_one_cm"],
|
|
"Fall Distance" => ["fall_one_cm"],
|
|
"Walk Under Water Distance" => ["walk_under_water_one_cm"],
|
|
"Walk On Water Distance" => ["walk_on_water_one_cm"],
|
|
}.each_pair do |stat_name, stat_fields|
|
|
dist = stat_fields.reduce(0) do |result, stat_field|
|
|
result + (stats["minecraft:custom"]["minecraft:#{stat_field}"] || 0)
|
|
end
|
|
# convert cm to m
|
|
dist = (dist + 500) / 1000
|
|
@all_stats[stat_name][user_name] = dist
|
|
end
|
|
end
|
|
|
|
def print_stats
|
|
@all_stats.each do |stat_name, stats|
|
|
next if stats.empty?
|
|
|
|
puts "== #{stat_name} =="
|
|
|
|
if stats.first.last.is_a?(Hash)
|
|
keys = stats.reduce([]) do |result, (player_name, stat_value)|
|
|
result + stat_value.keys
|
|
end.uniq.sort
|
|
puts "|= Player |= #{keys.join(" |= ")}"
|
|
stats.sort.each do |player_name, stat_value|
|
|
values = keys.map do |key|
|
|
stat_value[key]
|
|
end
|
|
puts "| #{player_name} | #{values.join(" | ")}"
|
|
end
|
|
else
|
|
puts "|= Player |= Value"
|
|
stats.sort.each do |player_name, stat_value|
|
|
puts "| #{player_name} | #{stat_value}"
|
|
end
|
|
end
|
|
|
|
puts
|
|
|
|
if stat_name == "Unexplored Biomes"
|
|
puts("Common Unexplored Biomes: " + (ADVENTURE_BIOMES - @all_explored_biomes).sort.join(", "))
|
|
puts
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
GenStats.new.run
|