185 lines
4.7 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" => {},
}
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
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