1
0
mirror of synced 2024-11-14 18:07:36 +01:00
bemaniutils/bemani/utils/trafficgen.py

572 lines
16 KiB
Python

import argparse
import sys
from typing import Any, Dict, Optional
import yaml
from bemani.client import ClientProtocol, BaseClient
from bemani.client.iidx import (
IIDXTricoroClient,
IIDXSpadaClient,
IIDXPendualClient,
IIDXCopulaClient,
IIDXSinobuzClient,
IIDXCannonBallersClient,
IIDXRootageClient,
)
from bemani.client.jubeat import (
JubeatSaucerClient,
JubeatSaucerFulfillClient,
JubeatPropClient,
JubeatQubellClient,
JubeatClanClient,
)
from bemani.client.popn import (
PopnMusicTuneStreetClient,
PopnMusicFantasiaClient,
PopnMusicSunnyParkClient,
PopnMusicLapistoriaClient,
PopnMusicEclaleClient,
PopnMusicUsaNekoClient,
)
from bemani.client.ddr import (
DDRX2Client,
DDRX3Client,
DDR2013Client,
DDR2014Client,
DDRAceClient,
)
from bemani.client.sdvx import (
SoundVoltexBoothClient,
SoundVoltexInfiniteInfectionClient,
SoundVoltexGravityWarsS1Client,
SoundVoltexGravityWarsS2Client,
SoundVoltexHeavenlyHavenClient,
)
from bemani.client.museca import (
Museca1Client,
Museca1PlusClient,
)
from bemani.client.reflec import (
ReflecBeat,
ReflecBeatLimelight,
ReflecBeatColette,
ReflecBeatGroovinUpper,
ReflecBeatVolzza,
ReflecBeatVolzza2,
)
from bemani.client.bishi import TheStarBishiBashiClient
def get_client(proto: ClientProtocol, pcbid: str, game: str, config: Dict[str, Any]) -> BaseClient:
if game == 'pnm-tune-street':
return PopnMusicTuneStreetClient(
proto,
pcbid,
config,
)
if game == 'pnm-fantasia':
return PopnMusicFantasiaClient(
proto,
pcbid,
config,
)
if game == 'pnm-sunny-park':
return PopnMusicSunnyParkClient(
proto,
pcbid,
config,
)
if game == 'pnm-lapistoria':
return PopnMusicLapistoriaClient(
proto,
pcbid,
config,
)
if game == 'pnm-eclale':
return PopnMusicEclaleClient(
proto,
pcbid,
config,
)
if game == 'pnm-usaneko':
return PopnMusicUsaNekoClient(
proto,
pcbid,
config,
)
if game == 'jubeat-saucer':
return JubeatSaucerClient(
proto,
pcbid,
config,
)
if game == 'jubeat-saucer-fulfill':
return JubeatSaucerFulfillClient(
proto,
pcbid,
config,
)
if game == 'jubeat-prop':
return JubeatPropClient(
proto,
pcbid,
config,
)
if game == 'jubeat-qubell':
return JubeatQubellClient(
proto,
pcbid,
config,
)
if game == 'jubeat-clan':
return JubeatClanClient(
proto,
pcbid,
config,
)
if game == 'iidx-rootage':
return IIDXRootageClient(
proto,
pcbid,
config,
)
if game == 'iidx-cannonballers':
return IIDXCannonBallersClient(
proto,
pcbid,
config,
)
if game == 'iidx-sinobuz':
return IIDXSinobuzClient(
proto,
pcbid,
config,
)
if game == 'iidx-copula':
return IIDXCopulaClient(
proto,
pcbid,
config,
)
if game == 'iidx-pendual':
return IIDXPendualClient(
proto,
pcbid,
config,
)
if game == 'iidx-spada':
return IIDXSpadaClient(
proto,
pcbid,
config,
)
if game == 'iidx-tricoro':
return IIDXTricoroClient(
proto,
pcbid,
config,
)
if game == 'bishi':
return TheStarBishiBashiClient(
proto,
pcbid,
config,
)
if game == 'ddr-x2':
return DDRX2Client(
proto,
pcbid,
config,
)
if game == 'ddr-x3':
return DDRX3Client(
proto,
pcbid,
config,
)
if game == 'ddr-2013':
return DDR2013Client(
proto,
pcbid,
config,
)
if game == 'ddr-2014':
return DDR2014Client(
proto,
pcbid,
config,
)
if game == 'ddr-ace':
return DDRAceClient(
proto,
pcbid,
config,
)
if game == 'sdvx-booth':
return SoundVoltexBoothClient(
proto,
pcbid,
config,
)
if game == 'sdvx-infinite-infection':
return SoundVoltexInfiniteInfectionClient(
proto,
pcbid,
config,
)
if game == 'sdvx-gravity-wars-s1':
return SoundVoltexGravityWarsS1Client(
proto,
pcbid,
config,
)
if game == 'sdvx-gravity-wars-s2':
return SoundVoltexGravityWarsS2Client(
proto,
pcbid,
config,
)
if game == 'sdvx-heavenly-haven':
return SoundVoltexHeavenlyHavenClient(
proto,
pcbid,
config,
)
if game == 'museca-1':
return Museca1Client(
proto,
pcbid,
config,
)
if game == 'museca-1+1/2':
return Museca1PlusClient(
proto,
pcbid,
config,
)
if game == 'reflec':
return ReflecBeat(
proto,
pcbid,
config,
)
if game == 'reflec-limelight':
return ReflecBeatLimelight(
proto,
pcbid,
config,
)
if game == 'reflec-colette':
return ReflecBeatColette(
proto,
pcbid,
config,
)
if game == 'reflec-groovin-upper':
return ReflecBeatGroovinUpper(
proto,
pcbid,
config,
)
if game == 'reflec-volzza':
return ReflecBeatVolzza(
proto,
pcbid,
config,
)
if game == 'reflec-volzza2':
return ReflecBeatVolzza2(
proto,
pcbid,
config,
)
raise Exception(f'Unknown game {game}')
def mainloop(address: str, port: int, configfile: str, action: str, game: str, cardid: Optional[str], verbose: bool) -> None:
games = {
'pnm-tune-street': {
'name': "Pop'n Music Tune Street",
'model': "K39:J:B:A:2010122200",
'old_profile_model': "J39:J:A:A",
'avs': None,
},
'pnm-fantasia': {
'name': "Pop'n Music Fantasia",
'model': "L39:J:B:A:2012091900",
'old_profile_model': "K39:J:A:A",
'avs': "2.13.6 r4921",
},
'pnm-sunny-park': {
'name': "Pop'n Music Sunny Park",
'model': "M39:J:B:A:2014061900",
'old_profile_model': "L39:J:A:A",
'avs': "2.15.8 r6631",
},
'pnm-lapistoria': {
'name': "Pop'n Music Lapistoria",
'model': "M39:J:B:A:2015081900",
'old_profile_model': "M39:J:B:A",
'avs': "2.15.8 r6631",
},
'pnm-eclale': {
'name': "Pop'n Music Eclale",
'model': "M39:J:B:A:2016100500",
'old_profile_model': "M39:J:B:A",
'avs': "2.15.8 r6631",
},
'pnm-usaneko': {
'name': "Pop'n Music Usagi to Neko to Shounen no Yume",
'model': "M39:J:B:A:2018101500",
'old_profile_model': "M39:J:B:A",
'avs': "2.15.8 r6631",
},
'jubeat-saucer': {
'name': "Jubeat Saucer",
'model': "L44:J:A:A:2014012802",
'avs': "2.15.8 r6631",
},
'jubeat-saucer-fulfill': {
'name': "Jubeat Saucer Fulfill",
'model': "L44:J:B:A:2014111800",
'avs': "2.15.8 r6631",
},
'jubeat-prop': {
'name': "Jubeat Prop",
'model': "L44:J:B:A:2016031700",
'avs': "2.15.8 r6631",
},
'jubeat-qubell': {
'name': "Jubeat Qubell",
'model': "L44:J:D:A:2016111400",
'avs': "2.15.8 r6631",
},
'jubeat-clan': {
'name': "Jubeat Clan",
'model': "L44:J:E:A:2018070901",
'avs': "2.17.3 r8311",
},
'iidx-rootage': {
'name': "Beatmania IIDX ROOTAGE",
'model': "LDJ:J:A:A:2019090200",
'avs': "2.17.0 r7883"
},
'iidx-cannonballers': {
'name': "Beatmania IIDX CANNON BALLERS",
'model': "LDJ:J:A:A:2018091900",
'avs': "2.17.0 r7883"
},
'iidx-sinobuz': {
'name': "Beatmania IIDX SINOBUZ",
'model': "LDJ:J:A:A:2017082800",
'avs': "2.16.1 r6901",
},
'iidx-copula': {
'name': "Beatmania IIDX copula",
'model': "LDJ:J:A:A:2016083100",
'avs': "2.16.1 r6901",
},
'iidx-pendual': {
'name': "Beatmania IIDX PENDUAL",
'model': "LDJ:A:A:A:2015080500",
'avs': "2.16.1 r6901",
},
'iidx-spada': {
'name': "Beatmania IIDX SPADA",
'model': "LDJ:A:A:A:2014071600",
'avs': "2.16.1 r6901",
},
'iidx-tricoro': {
'name': "Beatmania IIDX Tricoro",
'model': "LDJ:J:A:A:2013090900",
'avs': "2.15.8 r6631",
},
'bishi': {
'name': "The★BishiBashi",
'model': "IBB:A:A:A:2009092900",
'avs': None,
},
'ddr-x2': {
'name': "DanceDanceRevolution X2",
'model': "JDX:J:A:A:2010111000",
'avs': None,
},
'ddr-x3': {
'name': "DanceDanceRevolution X3 VS 2ndMIX",
'model': "KDX:J:A:A:2012112600",
'avs': "2.13.6 r4921",
},
'ddr-2013': {
'name': "DanceDanceRevolution (2013)",
'model': "MDX:J:A:A:2014032700",
'avs': "2.15.8 r6631",
},
'ddr-2014': {
'name': "DanceDanceRevolution (2014)",
'model': "MDX:A:A:A:2015122100",
'avs': "2.15.8 r6631",
},
'ddr-ace': {
'name': "DanceDanceRevolution A",
'model': "MDX:U:D:A:2017121400",
'avs': "2.15.8 r6631",
},
'sdvx-booth': {
'name': "SOUND VOLTEX BOOTH",
'model': "KFC:J:A:A:2013052900",
'avs': "2.15.8 r6631",
},
'sdvx-infinite-infection': {
'name': "SOUND VOLTEX II -infinite infection-",
'model': "KFC:J:A:A:2014102200",
'avs': "2.15.8 r6631",
},
'sdvx-gravity-wars-s1': {
'name': "SOUND VOLTEX III GRAVITY WARS Season 1",
'model': "KFC:J:A:A:2015111602",
'avs': "2.15.8 r6631",
},
'sdvx-gravity-wars-s2': {
'name': "SOUND VOLTEX III GRAVITY WARS Season 2",
'model': "KFC:J:A:A:2016121900",
'avs': "2.15.8 r6631",
},
'sdvx-heavenly-haven': {
'name': "SOUND VOLTEX IV HEAVENLY HAVEN",
'model': "KFC:J:A:A:2019020600",
'avs': "2.15.8 r6631",
},
'museca-1': {
'name': "MÚSECA",
'model': "PIX:J:A:A:2016071300",
'avs': "2.17.0 r7883",
},
'museca-1+1/2': {
'name': "MÚSECA 1+1/2",
'model': "PIX:J:A:A:2017042600",
'avs': "2.17.0 r7883",
},
'reflec': {
'name': "REFLEC BEAT",
'model': "KBR:A:A:A:2011112300",
'avs': None,
},
'reflec-limelight': {
'name': "REFLEC BEAT limelight",
'model': "LBR:A:A:A:2012082900",
'avs': "2.13.6 r4921",
},
'reflec-colette': {
'name': "REFLEC BEAT colette",
'model': "MBR:J:A:A:2014011600",
'avs': "2.15.8 r6631",
},
'reflec-groovin-upper': {
'name': "REFLEC BEAT groovin'!! Upper",
'model': "MBR:J:A:A:2015102100",
'avs': "2.15.8 r6631",
},
'reflec-volzza': {
'name': "REFLEC BEAT VOLZZA",
'model': "MBR:J:A:A:2016030200",
'avs': "2.15.8 r6631",
},
'reflec-volzza2': {
'name': "REFLEC BEAT VOLZZA 2",
'model': "MBR:J:A:A:2016100400",
'avs': "2.15.8 r6631",
},
}
if action == 'list':
for game in sorted([game for game in games]):
print(f'{game} - {games[game]["name"]}')
sys.exit(0)
if action == 'game':
if game not in games:
print(f'Unknown game {game}')
sys.exit(2)
config = yaml.safe_load(open(configfile))
print(f'Emulating {games[game]["name"]}')
emu = get_client(
ClientProtocol(
address,
port,
config['core']['encryption'],
config['core']['compression'],
verbose,
),
config['core']['pcbid'],
game,
games[game],
)
emu.verify(cardid)
def main() -> None:
parser = argparse.ArgumentParser(description="A utility to generate game-like traffic for testing an eAmusement server.")
parser.add_argument("-p", "--port", help="Port to talk to. Defaults to 80", type=int, default=80)
parser.add_argument("-a", "--address", help="Address to talk to. Defaults to 127.0.0.1", type=str, default="127.0.0.1")
parser.add_argument("-c", "--config", help="Core configuration. Defaults to trafficgen.yaml", type=str, default="trafficgen.yaml")
parser.add_argument("-g", "--game", help="The game that should be emulated. Should be one of the games returned by --list", type=str, default=None)
parser.add_argument("-l", "--list", help="List all known games and exit.", action="store_true")
parser.add_argument("-i", "--cardid", help="Use this card ID instead of a random one.", type=str, default=None)
parser.add_argument("-v", "--verbose", help="Print packets that are sent/received.", action='store_true', default=False)
args = parser.parse_args()
if args.list:
action = 'list'
game = None
elif args.game:
action = 'game'
game = args.game
else:
print("Unknown action to perform. Please specify --game <game> or --list")
sys.exit(1)
game = {
'pnm-19': 'pnm-tune-street',
'pnm-20': 'pnm-fantasia',
'pnm-21': 'pnm-sunny-park',
'pnm-22': 'pnm-lapistoria',
'pnm-23': 'pnm-eclale',
'pnm-24': 'pnm-usaneko',
'iidx-20': 'iidx-tricoro',
'iidx-21': 'iidx-spada',
'iidx-22': 'iidx-pendual',
'iidx-23': 'iidx-copula',
'iidx-24': 'iidx-sinobuz',
'iidx-25': 'iidx-cannonballers',
'iidx-26': 'iidx-rootage',
'jubeat-5': 'jubeat-saucer',
'jubeat-5+': 'jubeat-saucer-fulfill',
'jubeat-6': 'jubeat-prop',
'jubeat-7': 'jubeat-qubell',
'jubeat-8': 'jubeat-clan',
'ddr-12': 'ddr-x2',
'ddr-13': 'ddr-x3',
'ddr-14': 'ddr-2013',
'ddr-15': 'ddr-2014',
'ddr-16': 'ddr-ace',
'sdvx-1': 'sdvx-booth',
'sdvx-2': 'sdvx-infinite-infection',
'sdvx-3s1': 'sdvx-gravity-wars-s1',
'sdvx-3s2': 'sdvx-gravity-wars-s2',
'sdvx-4': 'sdvx-heavenly-haven',
'reflec-1': 'reflec',
'reflec-2': 'reflec-limelight',
'reflec-3': 'reflec-colette',
'reflec-4': 'reflec-groovin-upper',
'reflec-5': 'reflec-volzza',
'reflec-6': 'reflec-volzza2',
}.get(game, game)
mainloop(args.address, args.port, args.config, action, game, args.cardid, args.verbose)
if __name__ == '__main__':
main()