FF14の天気データをPythonで取得してみた
この記事では、FF14のオンラインゲームで各マップの天気情報を取得するPythonスクリプトの作り方が紹介されています。まずは地名リストを取得し、次にレアな天気である虹の予報時間を表示する方法が示されています。さらに、時差を考慮して時刻を表示する関数も提供されています。pipを使用してライブラリを活用することで、ゲーム内での天気情報を取得するスクリプト作成が可能です。
目次
この記事は、オンラインゲームのFF14における各マップの天気情報を取得するスクリプトの作り方を紹介します。「Python Advent Calendar 2024」14日目の記事として作成しました。
やりたかったこと
ゲーム内の各フィールドには一定時間周期で天気が変わるようになっています。釣りやゲーム内の写真(スクリーンショット)撮影などで、任意の地域で天気がどのように移り変わるかを知る方法としては、ゲーム内の天気予報士に話しかけることが一般的です。ただ、ある時GitHubにて天気予報データを取得できるPythonライブラリを発見しました。今回はこのコードをローカル環境で動かしてみようと思います。
セットアップ
仮想環境セットアップ
まずはPythonを実行する環境を作りましょう。ディレクトリを作成し、venvの作成とactivateを済ませます。
$ mkdir demo-app
$ pthon3 -m venv ff14_weather_forcast
source ff14_weather_forcast/bin/activate
(ff14_weather_forcast) %
ライブラリのインストール
続いて利用したいライブラリをpipからインストールします。日付の操作を行うため、datetime
も一緒にインストールしておきましょう。
(ff14_weather_forcast) % pip3 install eorzeaenv datetime
地名リストを取得する
早速ライブラリを利用してみましょう。まずは対応している地域を確認するため、地名リストを取得する処理を実装します。EorzeaEnv.Data.PlaceName
にDict形式で保存されていますので、言語を指定して出力させます。
from typing import List
from EorzeaEnv.Data.PlaceName import place_name
from EorzeaEnv.eorzea_lang import EorzeaLang
def get_eorzea_place_names(langs: List[EorzeaLang]):
"""
指定された言語でエオルゼアの地名リストを取得します。
Args:
langs (List[EorzeaLang]): 地名を取得する言語のリスト。デフォルトは日本語と英語。
Returns:
dict: 言語ごとの地名リストを含む辞書
"""
return {lang: list(place_name[lang].values()) for lang in langs}
def print_place_names_info(place_names: dict):
"""
取得した地名情報を表示します。
Args:
place_names (dict): 言語ごとの地名リストを含む辞書
"""
for lang, names in place_names.items():
print(f"{lang.name}の地名数: {len(names)}")
print(f"{lang.name}の最初の10個の地名:")
for name in names[:10]:
print(f" {name['place_name']} (index: {name['index']})")
print()
# 総地名数(最初の言語を基準とする)
first_lang = next(iter(place_names))
total_places = len(place_names[first_lang])
print(f"総地名数: {total_places}")
if __name__ == "__main__":
place_names = get_eorzea_place_names([EorzeaLang.JA, EorzeaLang.EN])
print_place_names_info(place_names)
このコードを実行すると、日本語と英語でDictの先頭10件を表示します。フィールドマップだけでなく、ダンジョンマップもサポートしている様子なのが、プレイヤーとしてはなかなか興味深いなと思いますね。
% python3 dev.py
JAの地名数: 438
JAの最初の10個の地名:
Gセイヴァー戦闘甲板 (index: 3663)
かいはつしつ (index: 1660)
アイズ・オブ・アレキサンダー (index: 1835)
アイティオン星晶鏡 (index: 4146)
アクアポリス (index: 1799)
アク・アファー円形劇場 (index: 1399)
アジス・ラー (index: 2101)
アジムステップ (index: 2411)
アトラス山頂 (index: 3217)
アドミラルブリッジ:提督室 (index: 351)
ENの地名数: 438
ENの最初の10個の地名:
The Abyssal Fracture (index: 4441)
The Aery (index: 2050)
The Aetherfont (index: 4297)
The Aetherial Slough (index: 4358)
Aetherochemical Research Facility (index: 2147)
Aglaia (index: 4167)
The Aitiascope (index: 4146)
Akadaemia Anyder (index: 3007)
Akh Afah Amphitheatre (index: 1399)
Ala Mhigo (index: 2691)
総地名数: 438
虹の予報を出す
続いてレアな天気の1つである虹がいつ出るかの予報もしてみましょう。EorzeaRainbow
という専用のクラスがありますので、EorzeaRainbow.forecast
を実行してUNIXTIMEで地域ごとの予報時間を取得します。あとはdatetime
を利用して読みやすいフォーマットに整形しましょう。
from datetime import datetime
from EorzeaEnv import EorzeaPlaceName, EorzeaRainbow, EorzeaTime, EorzeaWeather
rainbow_times: list[datetime] = []
place = EorzeaPlaceName("東ラノシア")
the_rainbow = EorzeaRainbow(place_name=place)
for t in EorzeaTime.weather_period(step='inf'):
the_rainbow.append(t, EorzeaWeather.forecast(place, t, raw=True))
if the_rainbow.is_appear:
unix_timestamp = t.get_unix_time()
rainbow_times.append(datetime.fromtimestamp(unix_timestamp))
if len(rainbow_times) == 20:
break
for time in rainbow_times:
print(time.strftime("%Y-%m-%d %H:%M:%S"))
実行すると、引数で渡した地域で虹が出る予定の時間(NOTゲーム内時間)が表示されます。このデータを使って、撮影などをおこなう日時を決めることができそうです。
% python3 dev.py
2024-10-21 02:03:20
2024-10-21 05:33:20
2024-10-22 13:03:20
2024-10-22 22:23:20
2024-10-25 18:26:40
2024-10-26 00:16:40
2024-10-26 04:56:40
2024-10-27 13:13:20
2024-10-27 17:06:40
2024-10-28 19:33:20
2024-10-28 20:43:20
出力結果はUTCタイムゾーンですので、日本時間へ変更することもできます。この場合、datetime
の変換処理にタイムゾーン名を渡しましょう。
from datetime import datetime
from EorzeaEnv import EorzeaPlaceName, EorzeaRainbow, EorzeaTime, EorzeaWeather
import pytz
def forecast_rainbow_times(place_name: str, count: int = 20, timezone: str = 'UTC') -> list[datetime]:
rainbow_times: list[datetime] = []
place = EorzeaPlaceName(place_name)
the_rainbow = EorzeaRainbow(place_name=place)
tz = pytz.timezone(timezone)
for t in EorzeaTime.weather_period(step='inf'):
weather = EorzeaWeather.forecast(place, t, raw=True)
the_rainbow.append(t, weather)
if the_rainbow.is_appear:
unix_timestamp = t.get_unix_time()
local_time = datetime.fromtimestamp(unix_timestamp, tz)
rainbow_times.append(local_time)
if len(rainbow_times) == count:
break
return rainbow_times
def print_rainbow_times(times: list[datetime], format: str = "%Y-%m-%d %H:%M:%S %Z"):
for time in times:
print(time.strftime(format))
# 使用例
if __name__ == "__main__":
place_name = "東ラノシア"
count = 20
timezone = "Asia/Tokyo" # 日本時間の例
rainbow_times = forecast_rainbow_times(place_name, count, timezone)
print(f"{place_name}の次の{count}回の虹の出現時刻 ({timezone}):")
print_rainbow_times(rainbow_times)
# 別のタイムゾーンでの表示例
print("\nUTCでの表示:")
print_rainbow_times([time.astimezone(pytz.UTC) for time in rainbow_times])
まとめ
pipで公開されているライブラリを使うことで、FF14ゲーム内の各エリアでの天気情報を取得するスクリプトが作れます。LINEなどと連携させると、便利そうかなと思いますので、他のファンツールなどを見ながら遊んでみようかなと思います。